Saya pikir keuntungannya adalah Anda benar-benar mengurangi jumlah penyalinan data yang diperlukan melalui metode tradisional membaca file.
Jika aplikasi Anda dapat menggunakan data "di tempat" dalam file yang dipetakan dengan memori, itu bisa masuk tanpa disalin; jika Anda menggunakan panggilan sistem (misalnya, pread Linux ()) maka itu biasanya melibatkan kernel yang menyalin data dari buffernya sendiri ke ruang pengguna. Penyalinan ekstra ini tidak hanya membutuhkan waktu, tetapi juga mengurangi keefektifan cache CPU dengan mengakses salinan data tambahan ini.
Jika data benar-benar harus dibaca dari disk (seperti pada I / O fisik), maka OS masih harus membacanya, kesalahan halaman mungkin tidak lebih baik dari segi kinerja daripada panggilan sistem, tetapi jika mereka jangan (yaitu sudah ada di cache OS), kinerja seharusnya secara teori jauh lebih baik.
Sisi negatifnya, tidak ada antarmuka asinkron ke file yang dipetakan dengan memori - jika Anda mencoba mengakses halaman yang tidak dipetakan, itu menghasilkan kesalahan halaman kemudian membuat utas menunggu I / O.
Kerugian yang jelas dari file yang dipetakan ke memori ada pada OS 32-bit - Anda dapat dengan mudah kehabisan ruang alamat.
Saya telah menggunakan file yang dipetakan memori untuk menerapkan fitur 'auto complete' saat pengguna mengetik. Saya memiliki lebih dari 1 juta nomor komponen produk yang disimpan dalam satu file indeks. File memiliki beberapa informasi tajuk yang khas tetapi sebagian besar file adalah larik raksasa dari catatan ukuran tetap yang diurutkan pada bidang kunci.
Saat runtime, file tersebut dipetakan dengan memori, ditransmisikan ke array
C
gayastruct
, dan kami melakukan pencarian biner untuk menemukan nomor bagian yang cocok saat pengguna mengetik. Hanya beberapa halaman memori dari file yang benar-benar dibaca dari disk - halaman mana pun yang terkena selama pencarian biner.sumber
File yang dipetakan memori dapat digunakan untuk menggantikan akses baca / tulis, atau untuk mendukung berbagi secara bersamaan. Saat Anda menggunakannya untuk satu mekanisme, Anda juga mendapatkan yang lain.
Daripada mencari dan menulis serta membaca dalam sebuah file, Anda memetakannya ke dalam memori dan cukup mengakses bit di tempat yang Anda harapkan.
Ini bisa sangat berguna, dan tergantung pada antarmuka memori virtual dapat meningkatkan kinerja. Peningkatan kinerja dapat terjadi karena sistem operasi sekarang dapat mengelola "file I / O" sebelumnya ini bersama dengan semua akses memori terprogram Anda yang lain, dan dapat (secara teori) memanfaatkan algoritme paging dan sebagainya yang sudah digunakannya untuk mendukung memori virtual untuk sisa program Anda. Namun, itu tergantung pada kualitas sistem memori virtual Anda. Anekdot Saya pernah mendengar mengatakan bahwa sistem memori virtual Solaris dan * BSD mungkin menunjukkan peningkatan kinerja yang lebih baik daripada sistem VM Linux - tetapi saya tidak memiliki data empiris untuk mendukungnya. YMMV.
Konkurensi muncul saat Anda mempertimbangkan kemungkinan beberapa proses menggunakan "file" yang sama melalui memori yang dipetakan. Dalam model baca / tulis, jika dua proses menulis ke area file yang sama, Anda dapat yakin bahwa salah satu data proses akan tiba di file, menimpa data proses lainnya. Anda akan mendapatkan satu, atau yang lain - tetapi bukan percampuran yang aneh. Saya harus mengakui bahwa saya tidak yakin apakah ini adalah perilaku yang diamanatkan oleh standar apa pun, tetapi ini adalah sesuatu yang dapat Anda andalkan. (Ini sebenarnya pertanyaan lanjutan yang bagus!)
Sebaliknya, dalam dunia yang dipetakan, bayangkan dua proses yang keduanya "menulis". Mereka melakukannya dengan melakukan "penyimpanan memori", yang menghasilkan O / S memindahkan data ke disk - pada akhirnya. Namun sementara itu, penulisan yang tumpang tindih dapat terjadi.
Berikut contohnya. Katakanlah saya memiliki dua proses yang keduanya menulis 8 byte pada offset 1024. Proses 1 menulis '11111111' dan proses 2 menulis '22222222'. Jika mereka menggunakan file I / O, maka bisa dibayangkan, jauh di dalam O / S, ada buffer penuh 1s, dan buffer penuh 2s, keduanya menuju ke tempat yang sama di disk. Salah satunya akan sampai di sana lebih dulu, dan yang lainnya akan sampai di sana lebih dulu, dan yang lainnya akan sampai di sana lebih dulu. Dalam hal ini, yang kedua menang. Namun , jika saya menggunakan pendekatan file yang dipetakan memori, proses 1 akan menggunakan penyimpanan memori 4 byte, diikuti oleh penyimpanan memori lain sebesar 4 byte (anggap saja itu bukan ukuran penyimpanan memori maksimum). Proses 2 akan melakukan hal yang sama. Berdasarkan kapan proses berjalan, Anda dapat melihat salah satu dari yang berikut ini:
Solusi untuk ini adalah dengan menggunakan pengecualian timbal balik eksplisit - yang mungkin merupakan ide bagus dalam acara apa pun. Anda semacam mengandalkan O / S untuk melakukan "hal yang benar" dalam kasus I / O file baca / tulis.
Primitif eksklusi mutual classing adalah mutex. Untuk file yang dipetakan memori, saya sarankan Anda melihat mutex yang dipetakan memori, tersedia menggunakan (misalnya) pthread_mutex_init ().
Edit dengan satu gotcha: Saat Anda menggunakan file yang dipetakan, ada godaan untuk menanamkan pointer ke data di file, di file itu sendiri (pikirkan daftar tertaut yang disimpan di file yang dipetakan). Anda tidak ingin melakukan itu, karena file mungkin dipetakan di alamat absolut yang berbeda pada waktu yang berbeda, atau dalam proses yang berbeda. Sebagai gantinya, gunakan offset dalam file yang dipetakan.
sumber
Konkurensi akan menjadi masalah. Akses acak lebih mudah. Performa bagus hingga hebat. Kemudahan penggunaan. Tidak terlalu bagus. Portabilitas - tidak terlalu panas.
Saya telah menggunakannya di sistem Matahari sejak lama, dan itu adalah pikiran saya.
sumber