Betriebssysteme führen E / A-Operationen in Speicherbereichen aus. Diese Speicherbereiche sind für das Betriebssystem zusammenhängende Folgen von Bytes. Kein Wunder also, dass nur Bytepuffer zur Teilnahme an E / A-Vorgängen berechtigt sind. Denken Sie auch daran, dass das Betriebssystem direkt auf den Adressraum des Prozesses zugreift, in diesem Fall auf den JVM-Prozess, um die Daten zu übertragen. Dies bedeutet, dass Speicherbereiche, die Ziele von E / A-Perationen sind, zusammenhängende Folgen von Bytes sein müssen. In der JVM wird ein Array von Bytes möglicherweise nicht zusammenhängend im Speicher gespeichert, oder der Garbage Collector kann es jederzeit verschieben. Arrays sind Objekte in Java, und die Art und Weise, wie Daten in diesem Objekt gespeichert werden, kann von einer JVM-Implementierung zur anderen variieren.
Aus diesem Grund wurde der Begriff eines direkten Puffers eingeführt. Direkte Puffer sind für die Interaktion mit Kanälen und nativen E / A-Routinen vorgesehen. Sie bemühen sich nach besten Kräften, die Byteelemente in einem Speicherbereich zu speichern, den ein Kanal für den direkten oder unformatierten Zugriff verwenden kann, indem sie nativen Code verwenden, um das Betriebssystem anzuweisen, den Speicherbereich direkt zu entleeren oder zu füllen.
Direktbytepuffer sind normalerweise die beste Wahl für E / A-Operationen. Sie unterstützen den effizientesten E / A-Mechanismus, der der JVM zur Verfügung steht. Nicht direkte Bytepuffer können an Kanäle übergeben werden, dies kann jedoch zu Leistungseinbußen führen. Es ist normalerweise nicht möglich, dass ein nicht direkter Puffer das Ziel einer nativen E / A-Operation ist. Wenn Sie ein nicht direktes ByteBuffer-Objekt zum Schreiben an einen Kanal übergeben, kann der Kanal bei jedem Aufruf implizit Folgendes ausführen:
- Erstellen Sie ein temporäres direktes ByteBuffer-Objekt.
- Kopieren Sie den Inhalt des nicht direkten Puffers in den temporären Puffer.
- Führen Sie die E / A-Operation auf niedriger Ebene mit dem temporären Puffer aus.
- Das temporäre Pufferobjekt verlässt den Gültigkeitsbereich und wird schließlich durch Müll gesammelt.
Dies kann möglicherweise zu Pufferkopien und Objektabwanderung bei jeder E / A führen. Dies sind genau die Dinge, die wir vermeiden möchten. Abhängig von der Implementierung sind die Dinge jedoch möglicherweise nicht so schlecht. Die Laufzeit wird wahrscheinlich direkte Puffer zwischenspeichern und wiederverwenden oder andere clevere Tricks ausführen, um den Durchsatz zu steigern. Wenn Sie lediglich einen Puffer für die einmalige Verwendung erstellen, ist der Unterschied nicht signifikant. Wenn Sie den Puffer jedoch in einem Hochleistungsszenario wiederholt verwenden, ist es besser, direkte Puffer zuzuweisen und wiederzuverwenden.
Direkte Puffer sind für E / A optimal, ihre Erstellung ist jedoch möglicherweise teurer als nicht direkte Bytepuffer. Der von direkten Puffern verwendete Speicher wird durch Aufrufen von nativem, betriebssystemspezifischem Code unter Umgehung des Standard-JVM-Heaps zugewiesen. Das Einrichten und Herunterfahren von direkten Puffern kann je nach Host-Betriebssystem und JVM-Implementierung erheblich teurer sein als Heap-residente Puffer. Die Speicherbereiche von Direktpuffern unterliegen keiner Speicherbereinigung, da sie sich außerhalb des Standard-JVM-Heaps befinden.
Die Leistungskompromisse bei der Verwendung von direkten und nicht direkten Puffern können je nach JVM, Betriebssystem und Code-Design stark variieren. Indem Sie Speicher außerhalb des Heapspeichers zuweisen, können Sie Ihre Anwendung zusätzlichen Kräften aussetzen, von denen die JVM nichts weiß. Stellen Sie sicher, dass Sie den gewünschten Effekt erzielen, wenn Sie zusätzliche bewegliche Teile ins Spiel bringen. Ich empfehle die alte Software-Maxime: Lass es zuerst funktionieren, dann mache es schnell. Sorgen Sie sich nicht zu sehr um die Optimierung im Vorfeld. Konzentrieren Sie sich zuerst auf die Richtigkeit. Die JVM-Implementierung kann möglicherweise Puffer-Caching oder andere Optimierungen durchführen, die Ihnen die Leistung bieten, die Sie benötigen, ohne dass Sie unnötigen Aufwand betreiben müssen.