I sistemi operativi eseguono operazioni di I / O su aree di memoria. Queste aree di memoria, per quanto riguarda il sistema operativo, sono sequenze contigue di byte. Non sorprende quindi che solo i buffer di byte siano idonei a partecipare alle operazioni di I / O. Ricorda inoltre che il sistema operativo accederà direttamente allo spazio degli indirizzi del processo, in questo caso il processo JVM, per trasferire i dati. Ciò significa che le aree di memoria che sono target delle perazioni I / O devono essere sequenze contigue di byte. Nella JVM, un array di byte potrebbe non essere archiviato in modo contiguo nella memoria, oppure Garbage Collector potrebbe spostarlo in qualsiasi momento. Le matrici sono oggetti in Java e il modo in cui i dati sono archiviati all'interno di tale oggetto può variare da un'implementazione JVM a un'altra.
Per questo motivo, è stata introdotta la nozione di buffer diretto. I buffer diretti sono destinati all'interazione con i canali e le routine di I / O native. Fanno il possibile per memorizzare gli elementi byte in un'area di memoria che un canale può utilizzare per l'accesso diretto o non elaborato utilizzando il codice nativo per indicare al sistema operativo di svuotare o riempire direttamente l'area di memoria.
I buffer di byte diretti sono in genere la scelta migliore per le operazioni di I / O. In base alla progettazione, supportano il meccanismo I / O più efficiente disponibile per la JVM. I buffer di byte non diretti possono essere passati ai canali, ma ciò potrebbe comportare una penalità di prestazione. Di solito non è possibile che un buffer non diretto sia la destinazione di un'operazione di I / O nativa. Se si passa un oggetto ByteBuffer non diretto a un canale per la scrittura, il canale può implicitamente eseguire le seguenti operazioni su ogni chiamata:
- Creare un oggetto ByteBuffer temporaneo diretto.
- Copia il contenuto del buffer non indiretto nel buffer temporaneo.
- Eseguire l'operazione di I / O di basso livello utilizzando il buffer temporaneo.
- L'oggetto buffer temporaneo non rientra nell'ambito di applicazione e viene infine garbage collection.
Ciò può potenzialmente comportare la copia del buffer e lo sfasamento degli oggetti su ogni I / O, che sono esattamente il genere di cose che vorremmo evitare. Tuttavia, a seconda dell'implementazione, le cose potrebbero non andare così male. Il runtime probabilmente memorizzerà nella cache e riutilizzerà i buffer diretti o eseguirà altri trucchi intelligenti per aumentare la velocità effettiva. Se stai semplicemente creando un buffer per l'uso singolo, la differenza non è significativa. D'altra parte, se si utilizzerà ripetutamente il buffer in uno scenario ad alte prestazioni, è meglio allocare i buffer diretti e riutilizzarli.
I buffer diretti sono ottimali per l'I / O, ma possono essere più costosi da creare rispetto ai buffer di byte non diretti. La memoria utilizzata dai buffer diretti viene allocata chiamando il codice nativo specifico del sistema operativo, ignorando l'heap JVM standard. L'impostazione e lo smantellamento dei buffer diretti potrebbe essere significativamente più costoso rispetto ai buffer residenti in heap, a seconda del sistema operativo host e dell'implementazione di JVM. Le aree di memoria dei buffer diretti non sono soggette alla garbage collection perché si trovano al di fuori dell'heap JVM standard.
I compromessi prestazionali dell'utilizzo di buffer diretti rispetto a quelli non diretti possono variare ampiamente in base a JVM, sistema operativo e progettazione del codice. Allocando la memoria all'esterno dell'heap, è possibile sottoporre l'applicazione a forze aggiuntive di cui la JVM non è a conoscenza. Quando si mettono in gioco ulteriori parti in movimento, assicurarsi di ottenere l'effetto desiderato. Consiglio la vecchia massima del software: prima fatelo funzionare, poi fatelo veloce. Non preoccuparti troppo dell'ottimizzazione iniziale; concentrarsi prima sulla correttezza. L'implementazione di JVM potrebbe essere in grado di eseguire la memorizzazione nella cache del buffer o altre ottimizzazioni che ti offriranno le prestazioni di cui hai bisogno senza troppi sforzi inutili da parte tua.