Sistem operasi melakukan operasi I / O pada area memori. Area memori ini, sejauh menyangkut sistem operasi, adalah urutan byte yang berdekatan. Maka tidak mengherankan bahwa hanya buffer byte yang memenuhi syarat untuk berpartisipasi dalam operasi I / O. Ingat juga bahwa sistem operasi akan secara langsung mengakses ruang alamat proses, dalam hal ini proses JVM, untuk mentransfer data. Ini berarti bahwa area memori yang menjadi target operasi I / O harus bersebelahan dengan urutan byte. Dalam JVM, array byte mungkin tidak disimpan secara bersamaan di memori, atau Pengumpul Sampah dapat memindahkannya kapan saja. Array adalah objek di Jawa, dan cara data disimpan di dalam objek itu bisa bervariasi dari satu implementasi JVM ke yang lain.
Untuk alasan ini, gagasan buffer langsung diperkenalkan. Buffer langsung dimaksudkan untuk interaksi dengan saluran dan rutin I / O asli. Mereka melakukan upaya terbaik untuk menyimpan elemen byte di area memori yang dapat digunakan saluran untuk akses langsung, atau mentah, dengan menggunakan kode asli untuk memberi tahu sistem operasi untuk mengalirkan atau mengisi area memori secara langsung.
Buffer byte langsung biasanya merupakan pilihan terbaik untuk operasi I / O. Secara desain, mereka mendukung mekanisme I / O paling efisien yang tersedia untuk JVM. Buffer byte tidak langsung dapat diteruskan ke saluran, tetapi hal itu dapat dikenakan penalti kinerja. Biasanya tidak mungkin buffer tidak langsung menjadi target operasi I / O asli. Jika Anda meneruskan objek ByteBuffer tidak langsung ke saluran untuk menulis, saluran tersebut secara implisit dapat melakukan hal berikut pada setiap panggilan:
- Buat objek ByteBuffer langsung sementara.
- Salin konten buffer nondirect ke buffer sementara.
- Lakukan operasi I / O tingkat rendah menggunakan buffer sementara.
- Objek buffer sementara keluar dari ruang lingkup dan akhirnya dikumpulkan sampah.
Ini berpotensi menghasilkan penyalinan buffer dan objek churn pada setiap I / O, yang persis seperti hal-hal yang ingin kita hindari. Namun, tergantung pada implementasinya, semuanya mungkin tidak seburuk ini. Runtime kemungkinan akan melakukan cache dan menggunakan kembali buffer langsung atau melakukan trik pintar lainnya untuk meningkatkan throughput. Jika Anda hanya membuat buffer untuk sekali pakai, perbedaannya tidak signifikan. Di sisi lain, jika Anda akan menggunakan buffer berulang kali dalam skenario kinerja tinggi, Anda lebih baik mengalokasikan buffer langsung dan menggunakannya kembali.
Buffer langsung optimal untuk I / O, tetapi mereka mungkin lebih mahal untuk dibuat daripada buffer byte tidak langsung. Memori yang digunakan oleh buffer langsung dialokasikan dengan memanggil kode asli, sistem operasi spesifik, melewati tumpukan JVM standar. Menyiapkan dan menghancurkan buffer langsung bisa jauh lebih mahal daripada buffer-residen, tergantung pada sistem operasi host dan implementasi JVM. Area penyimpanan memori buffer langsung tidak terkena pengumpulan sampah karena mereka berada di luar tumpukan JVM standar.
Pengorbanan kinerja menggunakan buffer langsung versus tidak langsung dapat sangat bervariasi menurut JVM, sistem operasi, dan desain kode. Dengan mengalokasikan memori di luar heap, Anda dapat membuat aplikasi Anda ke kekuatan tambahan yang JVM tidak sadari. Saat memainkan komponen bergerak tambahan, pastikan Anda mencapai efek yang diinginkan. Saya merekomendasikan pepatah perangkat lunak lama: pertama membuatnya bekerja, kemudian membuatnya cepat. Jangan terlalu khawatir tentang pengoptimalan di muka; berkonsentrasi pertama pada kebenaran. Implementasi JVM mungkin dapat melakukan caching buffer atau optimasi lain yang akan memberi Anda kinerja yang Anda butuhkan tanpa banyak upaya yang tidak perlu di pihak Anda.