Apa keuntungan dari file yang dipetakan memori?

89

Saya telah meneliti file yang dipetakan memori untuk sebuah proyek dan akan menghargai pemikiran apa pun dari orang-orang yang telah menggunakannya sebelumnya, atau memutuskan untuk tidak menggunakannya, dan mengapa?

Secara khusus, saya prihatin tentang yang berikut ini, dalam urutan kepentingannya:

  • konkurensi
  • akses acak
  • kinerja
  • kemudahan penggunaan
  • portabilitas
robottobor
sumber

Jawaban:

56

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.

MarkR
sumber
4
Pada Windows setidaknya Anda dapat memetakan beberapa tampilan 32bit dari file mmap yang lebih besar - yang bisa lebih efisien daripada mencoba menangani file yang sangat besar menggunakan fungsi CRT biasa
Martin Beckett
@MarkR Anda menulis "penyalinan tambahannya tidak hanya membutuhkan waktu, tetapi juga mengurangi efektivitas cache CPU dengan mengakses salinan data tambahan ini. ". ( penekanan saya). Bisakah Anda menjelaskan bagaimana salinan buffer tambahan di kernel menghalangi keefektifan cache CPU?
Geek
4
@Geek mengakses dua kali lebih banyak memori = dua kali lebih banyak cache yang terbuang (kira-kira).
pengguna253751
49

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 Cgaya struct, 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.

  • Concurrency - Saya memiliki masalah implementasi dimana terkadang memori memetakan file beberapa kali dalam ruang proses yang sama. Ini adalah masalah yang saya ingat karena terkadang sistem tidak dapat menemukan blok memori virtual yang cukup besar untuk memetakan file. Solusinya adalah hanya memetakan file satu kali dan menolak semua panggilan ke sana. Dalam retrospeksi menggunakan layanan Windows yang lengkap pasti keren.
  • Akses Acak - Pencarian biner tentu saja merupakan akses acak dan secepat kilat
  • Performa - Pencariannya sangat cepat. Saat pengguna mengetik, jendela popup menampilkan daftar nomor komponen produk yang cocok, daftar tersebut menyusut saat mereka terus mengetik. Tidak ada jeda yang terlihat saat mengetik.
Brian Ensink
sumber
1
Bukankah pencarian biner akan lambat karena halaman dibaca untuk setiap percobaan? Atau apakah sistem operasinya cukup pintar untuk menangani ini dengan cara yang efisien?
jjxtra
1
Saya kira menggunakan I / O yang dipetakan memori agak boros untuk pencarian biner, karena pencarian hanya akan mengakses beberapa kunci tunggal di lokasi memori yang relatif jauh, tetapi OS akan memuat di halaman 4k untuk setiap permintaan tersebut. Tetapi sekali lagi, file dengan bagian-bagian tidak banyak berubah, jadi cache membantu menutupi hal ini. Tapi secara tegas, saya percaya bahwa pencarian / membaca tradisional akan lebih baik di sini. Akhirnya, 1 juta tidak banyak hari ini. Mengapa tidak menyimpan semuanya di RAM saja?
babi
5
@ the swine and PsychoDad jawaban asli saya adalah dari tahun 2008 dan implementasi sebenarnya dari fitur pelengkapan otomatis yang dipetakan memori ini sekitar 2004-2005 atau lebih. Mengkonsumsi 800-1000MB memori fisik untuk memuat seluruh file bukanlah solusi yang baik untuk basis pengguna kami. Solusi yang dipetakan memori sangat cepat dan efisien. Itu menendang-pantat dan saya mengingatnya dengan sayang dari hari-hari awal saya sebagai pengembang junior. :)
Brian Ensink
@ BrianEnsink: oke, itu masuk akal. saya tidak berharap setiap entri menjadi sebanyak 1kB. maka tentu saja pendekatan paged menjadi lebih efisien. bagus :)
babi
22

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:

11111111
22222222
11112222
22221111

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.

rawa
sumber
1

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.

Paul Nathan
sumber