Saya sedang mengerjakan program yang akan memproses file yang berpotensi 100GB atau lebih. File-file tersebut berisi kumpulan catatan panjang variabel. Saya telah menerapkan dan menjalankan pertama dan sekarang sedang mencari cara untuk meningkatkan kinerja, terutama dalam melakukan I / O lebih efisien karena file input akan dipindai berkali-kali.
Apakah ada aturan praktis untuk menggunakan mmap()
versus membaca dalam blok melalui fstream
pustaka C ++ ? Yang ingin saya lakukan adalah membaca blok besar dari disk menjadi buffer, memproses catatan lengkap dari buffer, dan kemudian membaca lebih lanjut.
The mmap()
kode berpotensi mendapatkan sangat berantakan karena mmap
'd blok perlu berbaring di halaman berukuran batas (pemahaman saya) dan catatan bisa berpotensi seperti di halaman batas. Dengan fstream
s, saya hanya bisa mencari ke awal catatan dan mulai membaca lagi, karena kita tidak terbatas pada membaca blok yang terletak pada batas ukuran halaman.
Bagaimana saya bisa memutuskan antara dua opsi ini tanpa benar-benar menulis implementasi yang lengkap terlebih dahulu? Adakah aturan praktis (misalnya, mmap()
2x lebih cepat) atau tes sederhana?
mmap()
adalah 2-6 kali lebih cepat daripada menggunakan syscalls, misread()
.Jawaban:
Saya mencoba untuk menemukan kata terakhir pada mmap / membaca kinerja di Linux dan saya menemukan posting bagus ( tautan ) di milis kernel Linux. Ini dari tahun 2000, jadi ada banyak perbaikan pada IO dan memori virtual di kernel sejak itu, tapi itu menjelaskan alasan mengapa
mmap
atauread
mungkin lebih cepat atau lebih lambat.mmap
memiliki lebih banyak overhead daripadaread
(sama sepertiepoll
memiliki lebih banyak overhead daripadapoll
, yang memiliki lebih banyak overhead daripadaread
). Mengubah pemetaan memori virtual adalah operasi yang cukup mahal pada beberapa prosesor karena alasan yang sama bahwa beralih di antara proses yang berbeda itu mahal.Namun,
read
, file Anda mungkin telah dihapus dari cache sejak lama. Ini tidak berlaku jika Anda menggunakan file dan segera membuangnya. (Jika Anda mencobamlock
halaman hanya untuk menyimpannya dalam cache, Anda mencoba mengakali cache disk dan kebodohan semacam ini jarang membantu kinerja sistem).Diskusi mmap / baca mengingatkan saya pada dua diskusi kinerja lainnya:
Beberapa programmer Java terkejut menemukan bahwa I / O nonblocking seringkali lebih lambat daripada memblokir I / O, yang masuk akal jika Anda tahu bahwa I / O nonblocking memerlukan membuat lebih banyak syscalls.
Beberapa pemrogram jaringan lain terkejut mengetahui bahwa
epoll
sering kali lebih lambat daripadapoll
, yang masuk akal jika Anda tahu bahwa pengelolaanepoll
membutuhkan lebih banyak panggilan syscalls.Kesimpulan: Gunakan peta memori jika Anda mengakses data secara acak, simpan di sana untuk waktu yang lama, atau jika Anda tahu Anda dapat membagikannya dengan proses lain (
MAP_SHARED
tidak terlalu menarik jika tidak ada pembagian yang sebenarnya). Baca file secara normal jika Anda mengakses data secara berurutan atau membuangnya setelah membaca. Dan jika salah satu metode membuat program Anda kurang kompleks, lakukan itu . Untuk banyak kasus di dunia nyata, tidak ada cara pasti untuk menunjukkan satu lebih cepat tanpa menguji aplikasi Anda yang sebenarnya dan BUKAN patokan.(Maaf karena membatalkan pertanyaan ini, tetapi saya sedang mencari jawaban dan pertanyaan ini terus muncul di bagian atas hasil Google.)
sumber
mmap
vsread()
di utas itu masih benar seperti sebelumnya, kinerja keseluruhan tidak dapat benar-benar ditentukan dengan menambahkan pro dan kontra, tetapi hanya dengan menguji pada konfigurasi perangkat keras tertentu. Misalnya, dapat diperdebatkan bahwa "Panggilan ke mmap memiliki lebih banyak overhead daripada membaca" - yammap
harus menambahkan pemetaan ke tabel halaman proses, tetapiread
harus menyalin semua byte baca dari kernel ke ruang pengguna.mmap
memiliki overhead yang lebih rendah daripadaread
untuk yang berukuran lebih besar daripada halaman (4 KiB). Sekarang sangat benar bahwa jika Anda ingin mengakses data secara jarang dan acak,mmap
itu benar-benar baik - tetapi sebaliknya tidak perlu benar:mmap
mungkin masih yang terbaik untuk akses berurutan juga.mmap
lebih cepat, saya berharap melihat minimal seluruh perangkat pengujian (kode sumber) dengan hasil yang ditabulasi, dan nomor model prosesor.mmap
tidak membilas TLB kecuali dalam keadaan yang tidak biasa (tapimunmap
mungkin). Tes saya termasuk microbenchmark (termasukmunmap
) dan juga "dalam aplikasi" yang berjalan dalam kasus penggunaan dunia nyata. Tentu saja aplikasi saya tidak sama dengan aplikasi Anda, jadi orang harus menguji secara lokal. Bahkan tidak jelas apakahmmap
yang disukai oleh benchmark mikro:read()
juga mendapat dorongan besar karena buffer tujuan sisi pengguna umumnya tetap di L1, yang mungkin tidak terjadi dalam aplikasi yang lebih besar. Jadi ya, "ini rumit".Biaya kinerja utama adalah disk i / o. "mmap ()" tentu saja lebih cepat daripada istream, tetapi perbedaannya mungkin tidak terlihat karena disk i / o akan mendominasi run-times Anda.
Saya mencoba fragmen kode Ben Collins (lihat di atas / di bawah) untuk menguji pernyataannya bahwa "mmap () jauh lebih cepat" dan tidak menemukan perbedaan yang dapat diukur. Lihat komentar saya pada jawabannya.
Saya pasti tidak akan merekomendasikan secara terpisah mmap'ing masing-masing catatan pada gilirannya kecuali "catatan" Anda besar - itu akan sangat lambat, membutuhkan 2 panggilan sistem untuk setiap catatan dan mungkin kehilangan halaman dari cache disk-memori .... .
Dalam kasus Anda, saya pikir mmap (), istream dan panggilan tingkat rendah terbuka () / baca () semua akan hampir sama. Saya akan merekomendasikan mmap () dalam kasus ini:
(btw - I love mmap () / MapViewOfFile ()).
sumber
mmap jauh lebih cepat. Anda dapat menulis tolok ukur sederhana untuk membuktikannya kepada diri sendiri:
melawan:
Jelas, saya meninggalkan detail (seperti bagaimana menentukan kapan Anda mencapai akhir file jika file Anda bukan kelipatan
page_size
, misalnya), tapi itu seharusnya tidak jauh lebih rumit dari ini .Jika Anda bisa, Anda dapat mencoba memecah data Anda menjadi beberapa file yang dapat mmap () - ed secara keseluruhan alih-alih sebagian (jauh lebih sederhana).
Beberapa bulan yang lalu saya menerapkan setengah-slide mmap () - ed stream class untuk boost_iostreams, tetapi tidak ada yang peduli dan saya sibuk dengan hal-hal lain. Sayangnya, saya menghapus arsip proyek yang belum selesai beberapa minggu yang lalu, dan itu adalah salah satu korban :-(
Pembaruan : Saya juga harus menambahkan peringatan bahwa benchmark ini akan terlihat sangat berbeda di Windows karena Microsoft menerapkan cache file bagus yang melakukan sebagian besar dari apa yang Anda lakukan dengan mmap di tempat pertama. Yaitu, untuk file yang sering diakses, Anda bisa melakukan std :: ifstream.read () dan itu akan secepat mmap, karena cache file sudah melakukan pemetaan memori untuk Anda, dan transparan.
Pembaruan Akhir : Lihat, orang-orang: di banyak kombinasi platform OS dan perpustakaan standar serta disk dan hierarki memori yang berbeda, saya tidak dapat mengatakan dengan pasti bahwa panggilan sistem
mmap
, dipandang sebagai kotak hitam, akan selalu selalu jauh lebih cepat secara substansial dariread
. Itu bukan maksud saya, bahkan jika kata-kata saya bisa ditafsirkan seperti itu. . Satu-satunya cara untuk benar-benar yakin bahwa Anda menggunakan i / o yang dipetakan dalam memori dengan cara portabel adalah dengan menggunakannya . Jika Anda tidak peduli tentang portabilitas dan Anda dapat mengandalkan karakteristik khusus platform target Anda, maka menggunakan mungkin cocok tanpa mengorbankan kinerja apa pun yang terukur.Pada akhirnya, maksud saya adalah bahwa memori yang dipetakan i / o umumnya lebih cepat dari byte berbasis i / o; ini masih benar . Jika Anda menemukan secara eksperimental bahwa tidak ada perbedaan antara keduanya, maka satu-satunya penjelasan yang tampaknya masuk akal bagi saya adalah bahwa platform Anda mengimplementasikan pemetaan memori di bawah penutup dengan cara yang menguntungkan bagi kinerja panggilan keread
mmap
read
Edit untuk membersihkan daftar jawaban: @ jbl:
Tentu - saya sedang menulis perpustakaan C ++ untuk Git (libgit ++, jika Anda mau), dan saya mengalami masalah yang sama dengan ini: Saya harus dapat membuka file besar (sangat besar) dan tidak memiliki kinerja menjadi total dog (Seperti halnya dengan
std::fstream
).Boost::Iostreams
sudah memiliki Sumber mapped_file, tetapi masalahnya adalah ia meng-mmap
ping seluruh file, yang membatasi Anda untuk 2 ^ (wordsize). Pada mesin 32-bit, 4GB tidak cukup besar. Bukan tidak masuk akal untuk berharap memiliki.pack
file di Git yang menjadi jauh lebih besar dari itu, jadi saya perlu membaca file dalam potongan tanpa menggunakan file i / o biasa. Di balik sampulBoost::Iostreams
, saya menerapkan Sumber, yang kurang lebih merupakan pandangan lain tentang interaksi antarastd::streambuf
danstd::istream
. Anda juga bisa mencoba pendekatan serupa dengan hanya mewarisistd::filebuf
ke dalammapped_filebuf
dan juga mewarisistd::fstream
ke dalama mapped_fstream
. Interaksi antara keduanya itulah yang sulit dilakukan dengan benar.Boost::Iostreams
memiliki beberapa pekerjaan yang dilakukan untuk Anda, dan juga menyediakan kait untuk filter dan rantai, jadi saya pikir akan lebih bermanfaat untuk menerapkannya dengan cara itu.sumber
mmap()
mengarsipkan halaman sekaligus? Jika asize_t
cukup luas untuk menampung ukuran file (sangat mungkin pada sistem 64-bit), maka hanyammap()
seluruh file dalam satu panggilan.Ada banyak jawaban bagus di sini yang sudah mencakup banyak poin penting, jadi saya hanya akan menambahkan beberapa masalah yang tidak saya lihat langsung di atas. Artinya, jawaban ini seharusnya tidak dianggap sebagai komprehensif dari pro dan kontra, tetapi merupakan tambahan untuk jawaban lain di sini.
mmap sepertinya sihir
Mengambil kasus di mana file sudah sepenuhnya di-cache 1 sebagai baseline 2 ,
mmap
mungkin tampak seperti sulap :mmap
hanya membutuhkan 1 panggilan sistem untuk (berpotensi) memetakan seluruh file, setelah itu tidak ada lagi panggilan sistem yang diperlukan.mmap
tidak memerlukan salinan data file dari kernel ke ruang pengguna.mmap
memungkinkan Anda untuk mengakses file "sebagai memori", termasuk memprosesnya dengan trik canggih apa pun yang dapat Anda lakukan terhadap memori, seperti kompilasi otomatis vektor, intrinsik SIMD , prefetching, rutinitas parsing dalam memori yang dioptimalkan, OpenMP, dll.Jika file tersebut sudah ada dalam cache, sepertinya tidak mungkin dikalahkan: Anda langsung mengakses cache halaman kernel sebagai memori dan itu tidak bisa lebih cepat dari itu.
Ya bisa.
mmap sebenarnya bukan sihir karena ...
mmap masih berfungsi per halaman
Biaya tersembunyi utama
mmap
vsread(2)
(yang sebenarnya merupakan syscall OS-level yang sebanding untuk membaca blok ) adalah bahwammap
Anda harus melakukan "beberapa pekerjaan" untuk setiap halaman 4K di ruang pengguna, meskipun mungkin disembunyikan oleh mekanisme kesalahan halaman.Sebagai contoh implementasi khas yang hanya
mmap
s seluruh file perlu kesalahan-in sehingga 100 GB / 4K = 25 juta kesalahan untuk membaca file 100 GB. Sekarang, ini akan menjadi kesalahan kecil , tetapi 25 miliar kesalahan halaman masih tidak akan menjadi super cepat. Biaya kesalahan kecil mungkin dalam 100-an nanos dalam kasus terbaik.mmap sangat bergantung pada kinerja TLB
Sekarang, Anda dapat meneruskan
MAP_POPULATE
untukmmap
mengatakannya untuk mengatur semua tabel halaman sebelum kembali, sehingga seharusnya tidak ada kesalahan halaman saat mengaksesnya. Sekarang, ini memiliki sedikit masalah karena ia juga membaca seluruh file menjadi RAM, yang akan meledak jika Anda mencoba memetakan file 100GB - tapi mari kita abaikan itu untuk saat ini 3 . Kernel perlu melakukan pekerjaan per halaman untuk mengatur tabel halaman ini (muncul sebagai waktu kernel). Ini akhirnya menjadi biaya besar dalammmap
pendekatan, dan itu sebanding dengan ukuran file (yaitu, itu tidak menjadi relatif kurang penting karena ukuran file bertambah) 4 .Akhirnya, bahkan dalam ruang pengguna mengakses pemetaan seperti itu tidak benar-benar gratis (dibandingkan dengan buffer memori besar yang tidak berasal dari berbasis file
mmap
) - bahkan setelah tabel halaman diatur, setiap akses ke halaman baru akan, secara konseptual, menimbulkan miss TLB. Karenammap
ing file berarti menggunakan cache halaman dan halaman 4K, Anda sekali lagi dikenai biaya 25 juta kali untuk file 100GB.Sekarang, biaya sebenarnya dari kehilangan TLB ini sangat bergantung pada setidaknya aspek-aspek berikut dari perangkat keras Anda: (a) berapa banyak 4K TLB yang Anda miliki dan bagaimana kinerja caching terjemahan lainnya bekerja (b) seberapa baik perangkat keras mengambil penawaran dengan dengan TLB - mis., dapatkah prefetch memicu berjalan halaman? (c) seberapa cepat dan sejajar dengan hardware berjalan halaman. Pada prosesor Intel high-end x86 modern, perangkat keras laman berjalan secara umum sangat kuat: setidaknya ada 2 pejalan halaman paralel, berjalan halaman dapat terjadi secara bersamaan dengan eksekusi lanjutan, dan pengambilan perangkat keras dapat memicu berjalannya halaman. Jadi dampak TLB pada beban baca streaming cukup rendah - dan beban seperti itu akan sering melakukan hal yang sama terlepas dari ukuran halaman. Namun, perangkat keras lain biasanya jauh lebih buruk!
baca () hindari perangkap ini
The
read()
syscall, yang adalah apa yang umumnya mendasari "blok membaca" jenis panggilan yang ditawarkan misalnya, di C, C ++ dan bahasa lainnya memiliki satu kelemahan utama bahwa setiap orang baik-menyadari:read()
panggilan N byte harus menyalin N byte dari kernel ke ruang pengguna.Di sisi lain, ia menghindari sebagian besar biaya di atas - Anda tidak perlu memetakan 25 juta halaman 4K ke dalam ruang pengguna. Anda biasanya dapat
malloc
buffer tunggal buffer kecil di ruang pengguna, dan menggunakannya kembali berulang kali untuk semuaread
panggilan Anda . Di sisi kernel, hampir tidak ada masalah dengan 4K halaman atau TLB meleset karena semua RAM biasanya dipetakan secara linear menggunakan beberapa halaman yang sangat besar (misalnya, 1 GB halaman pada x86), sehingga halaman yang mendasarinya di cache halaman tertutup. sangat efisien dalam ruang kernel.Jadi pada dasarnya Anda memiliki perbandingan berikut untuk menentukan mana yang lebih cepat untuk membaca satu file besar:
Apakah pekerjaan ekstra per halaman yang tersirat oleh
mmap
pendekatan ini lebih mahal daripada pekerjaan byte per menyalin konten file dari kernel ke ruang pengguna tersirat dengan menggunakanread()
?Pada banyak sistem, mereka sebenarnya kurang lebih seimbang. Perhatikan bahwa masing-masing skala dengan atribut perangkat keras dan tumpukan OS yang sangat berbeda.
Secara khusus,
mmap
pendekatan menjadi relatif lebih cepat ketika:MAP_POPULATE
implementasi yang baik yang dapat secara efisien memproses peta besar dalam kasus-kasus di mana, misalnya, halaman yang mendasarinya berdekatan dalam memori fisik.... sementara
read()
pendekatannya menjadi relatif lebih cepat ketika:read()
syscall memiliki kinerja salinan yang baik. Misalnya,copy_to_user
kinerja yang baik di sisi kernel.Faktor perangkat keras di atas sangat bervariasi di berbagai platform yang berbeda, bahkan dalam keluarga yang sama (misalnya, dalam generasi x86 dan terutama segmen pasar) dan tentunya lintas arsitektur (misalnya, ARM vs x86 vs PPC).
Faktor OS terus berubah juga, dengan berbagai peningkatan di kedua sisi menyebabkan lompatan besar dalam kecepatan relatif untuk satu pendekatan atau yang lain. Daftar terbaru termasuk:
mmap
kasus tanpaMAP_POPULATE
.copy_to_user
metode jalur cepat diarch/x86/lib/copy_user_64.S
, misalnya, menggunakanREP MOVQ
ketika itu cepat, yang sangat membanturead()
kasus ini.Perbarui setelah Specter dan Meltdown
Mitigasi untuk kerentanan Spectre dan Meltdown sangat meningkatkan biaya pemanggilan sistem. Pada sistem yang saya ukur, biaya pemanggilan sistem "tidak melakukan apa-apa" (yang merupakan perkiraan overhead murni dari pemanggilan sistem, terlepas dari pekerjaan aktual yang dilakukan oleh panggilan tersebut) naik dari sekitar 100 ns pada tipikal sistem Linux modern sekitar 700 ns. Lebih jauh, tergantung pada sistem Anda, perbaikan isolasi halaman-tabel khusus untuk Meltdown dapat memiliki efek hilir tambahan selain dari biaya panggilan sistem langsung karena kebutuhan untuk memuat ulang entri TLB.
Semua ini adalah kerugian relatif untuk
read()
metode berbasis dibandingkan denganmmap
metode berbasis, karenaread()
metode harus membuat satu panggilan sistem untuk setiap "ukuran buffer" nilai data. Anda tidak dapat secara sewenang-wenang meningkatkan ukuran buffer untuk mengamortisasi biaya ini karena menggunakan buffer besar biasanya berkinerja lebih buruk karena Anda melebihi ukuran L1 dan karenanya terus-menerus mengalami kesalahan cache.Di sisi lain, dengan
mmap
, Anda dapat memetakan di wilayah memori yang besar denganMAP_POPULATE
dan mengaksesnya secara efisien, dengan biaya hanya satu panggilan sistem.1 Ini kurang lebih juga termasuk kasus di mana file tidak sepenuhnya di-cache untuk memulai dengan, tetapi di mana OS read-depan cukup baik untuk membuatnya tampak begitu (yaitu, halaman biasanya di-cache pada saat Anda ingin). Ini adalah masalah yang halus karena cara baca-depan bekerja sering sangat berbeda antara
mmap
danread
panggilan, dan dapat lebih lanjut disesuaikan dengan panggilan "saran" seperti yang dijelaskan dalam 2 .2 ... karena jika file tersebut tidak di- cache, perilaku Anda akan sepenuhnya didominasi oleh kekhawatiran IO, termasuk seberapa simpatik pola akses Anda terhadap perangkat keras yang mendasarinya - dan semua usaha Anda harus memastikan bahwa akses tersebut sama simpatiknya dengan mungkin, misalnya melalui penggunaan
madvise
ataufadvise
panggilan (dan perubahan level aplikasi apa pun yang dapat Anda lakukan untuk meningkatkan pola akses).3 Anda bisa menyiasatinya, misalnya, dengan secara berurutan
mmap
masuk ke jendela dengan ukuran lebih kecil, katakanlah 100 MB.4 Faktanya, ternyata
MAP_POPULATE
pendekatannya adalah (setidaknya satu kombinasi beberapa hardware / OS) hanya sedikit lebih cepat daripada tidak menggunakannya, mungkin karena kernel menggunakan faultaround - sehingga jumlah sebenarnya dari kesalahan kecil dikurangi dengan faktor 16 atau lebih.sumber
mmap
akan memiliki keuntungan yang tidak dapat diatasi karena ia menghindari overhead panggilan kernel yang tetap. Di sisi lain,mmap
juga meningkatkan tekanan TLB, dan benar-benar membuat menjadi lebih lambat untuk fase "pemanasan" di mana byte sedang dibaca untuk pertama kalinya dalam proses saat ini (meskipun mereka masih di halaman halaman), karena mungkin lebih banyak pekerjaan daripadaread
, misalnya ke "kesalahan sekitar" halaman yang berdekatan ... dan untuk aplikasi yang sama "pemanasan" adalah yang terpenting! @CaetanoSauerMaaf Ben Collins kehilangan kode sumber windows mmap sliding-nya. Itu bagus untuk dimiliki di Boost.
Ya, memetakan file jauh lebih cepat. Anda pada dasarnya menggunakan subsistem memori virtual OS untuk mengaitkan memori ke disk dan sebaliknya. Pikirkan seperti ini: jika pengembang kernel OS dapat membuatnya lebih cepat, mereka akan melakukannya. Karena melakukan hal itu membuat segalanya menjadi lebih cepat: database, waktu boot, waktu buka program, dan sebagainya.
Pendekatan sliding window sebenarnya tidak terlalu sulit karena banyak halaman yang bisa dipetakan sekaligus. Jadi ukuran rekaman tidak masalah asalkan yang terbesar dari setiap rekaman akan masuk ke dalam memori. Yang penting adalah mengelola pembukuan.
Jika catatan tidak dimulai pada batas getpagesize (), pemetaan Anda harus dimulai pada halaman sebelumnya. Panjang wilayah yang dipetakan memanjang dari byte pertama catatan (dibulatkan ke bawah jika perlu hingga kelipatan getpagesize ()) terdekat ke byte terakhir dari catatan (dibulatkan ke kelipatan getpagesize terdekat ()). Saat Anda selesai memproses catatan, Anda dapat menghapus peta (), dan melanjutkan ke yang berikutnya.
Ini semua berfungsi dengan baik di bawah Windows juga menggunakan CreateFileMapping () dan MapViewOfFile () (dan GetSystemInfo () untuk mendapatkan SYSTEM_INFO.dwAllocationGranularity --- bukan SYSTEM_INFO.dwPageSize).
sumber
mmap harus lebih cepat, tetapi saya tidak tahu berapa banyak. Ini sangat tergantung pada kode Anda. Jika Anda menggunakan mmap yang terbaik adalah mmap seluruh file sekaligus, itu akan membuat hidup Anda jauh lebih mudah. Satu masalah potensial adalah bahwa jika file Anda lebih besar dari 4GB (atau dalam praktiknya batasnya lebih rendah, seringkali 2GB) Anda akan memerlukan arsitektur 64bit. Jadi jika Anda menggunakan lingkungan 32, Anda mungkin tidak ingin menggunakannya.
Karena itu, mungkin ada rute yang lebih baik untuk meningkatkan kinerja. Anda mengatakan file input akan dipindai berkali-kali , jika Anda bisa membacanya dalam satu pass dan kemudian selesai dengan itu, itu bisa berpotensi jauh lebih cepat.
sumber
Mungkin Anda harus melakukan pra-proses file, sehingga setiap catatan dalam file yang terpisah (atau setidaknya bahwa setiap file adalah ukuran yang mampu mmap).
Bisakah Anda melakukan semua langkah pemrosesan untuk setiap record, sebelum pindah ke yang berikutnya? Mungkin itu akan menghindari beberapa overhead IO?
sumber
Saya setuju bahwa file mmap'd I / O akan menjadi lebih cepat, tapi saat Anda pembandingan kode, seharusnya tidak counter contoh akan agak dioptimalkan?
Ben Collins menulis:
Saya sarankan juga mencoba:
Dan lebih dari itu, Anda mungkin juga mencoba membuat ukuran buffer dengan ukuran yang sama dengan satu halaman memori virtual, jika 0x1000 bukan ukuran satu halaman memori virtual pada mesin Anda ... IMHO mmap akan mengajukan I / O masih menang, tetapi ini harus membuat segalanya lebih dekat.
sumber
Menurut saya, menggunakan mmap () "hanya" mencabut pengembang dari harus menulis kode caching mereka sendiri. Dalam kasus sederhana "baca file sekali saja", ini tidak akan sulit (meskipun seperti yang ditunjukkan mlbrock Anda masih menyimpan salinan memori ke dalam ruang proses), tetapi jika Anda bolak-balik dalam file atau melewatkan bit dan sebagainya, saya percaya pengembang kernel mungkin telah melakukan pekerjaan yang lebih baik dalam mengimplementasikan caching daripada yang saya bisa ...
sumber
mmap
caching adalah Anda cukup menggunakan kembali cache halaman yang sudah ada yang sudah ada di sana, sehingga Anda mendapatkan memori itu secara gratis, dan itu dapat dibagikan di seluruh proses juga.Saya ingat memetakan file besar yang berisi struktur pohon ke memori tahun yang lalu. Saya kagum dengan kecepatan dibandingkan dengan normalisasi serialisasi yang melibatkan banyak pekerjaan dalam memori, seperti mengalokasikan node pohon dan pengaturan pointer. Jadi sebenarnya saya membandingkan satu panggilan ke mmap (atau rekannya di Windows) terhadap banyak (BANYAK) panggilan ke panggilan operator dan konstruktor baru. Untuk tugas semacam itu, mmap tidak terkalahkan dibandingkan dengan de-serialisasi. Tentu saja orang harus melihat ke dalam pointer relocatable untuk ini.
sumber
Ini kedengarannya seperti kasus penggunaan yang baik untuk multi-threading ... Saya pikir Anda bisa dengan mudah mengatur satu utas untuk membaca data sementara yang lain memprosesnya. Itu mungkin cara untuk secara dramatis meningkatkan kinerja yang dirasakan. Hanya pemikiran saja.
sumber
Saya pikir hal terbesar tentang mmap berpotensi membaca asinkron dengan:
Masalahnya adalah saya tidak dapat menemukan MAP_FLAGS yang tepat untuk memberikan petunjuk bahwa memori ini harus disinkronkan dari file secepatnya. Saya harap MAP_POPULATE memberikan petunjuk yang tepat untuk mmap (artinya ia tidak akan mencoba memuat semua konten sebelum kembali dari panggilan, tetapi akan melakukannya dalam async. Dengan feed_data). Setidaknya itu memberikan hasil yang lebih baik dengan flag ini bahkan manual itu menyatakan bahwa ia tidak melakukan apa-apa tanpa MAP_PRIVATE sejak 2.6.23.
sumber
posix_madvise
denganWILLNEED
bendera untuk petunjuk malas untuk mengisi lebih dulu.posix_madvise
adalah panggilan async. Juga akan menyenangkan untuk referensimlock
bagi mereka yang ingin menunggu sampai seluruh wilayah memori tersedia tanpa kesalahan halaman.