Slyšel jsem (někde jsem to četl na internetu), že mmap() je rychlejší než sekvenční IO. Je to správně? Pokud ano, proč je rychlejší?
Může být - existují výhody a nevýhody, které jsou uvedeny níže. Když máte opravdu důvod se starat, vždy porovnejte obojí .
Kromě skutečné efektivity IO existují důsledky pro způsob, jakým kód aplikace sleduje, kdy potřebuje provést I/O, a jak zpracovává/generuje data, což může někdy dost dramaticky ovlivnit výkon.
- mmap() nečte sekvenčně.2) mmap() se musí načítat z disku samotného stejně jako read() dělá3) Mapovaná oblast není sekvenční – takže žádné DMA (?).
Takže mmap() by mělo být ve skutečnosti pomalejší než read() ze souboru? Které z mých výše uvedených předpokladů jsou nesprávné?
-
je špatně...
mmap()
přiřazuje oblast virtuálního adresního prostoru odpovídající obsahu souboru... kdykoli se přistoupí na stránku v tomto adresovém prostoru, je nalezena fyzická RAM, která zálohuje virtuální adresy, a odpovídající obsah disku je zapsán do této RAM. Pořadí, ve kterém se provádí čtení z disku, tedy odpovídá pořadí přístupu. Je to "líný" I/O mechanismus. Pokud jste například potřebovali indexovat do velké hashovací tabulky, která se měla číst z disku, pakmmap
Pokud soubor spustíte a začnete přistupovat, znamená to, že vstup/výstup na disku neprobíhá sekvenčně, a proto může trvat delší dobu, než je celý soubor načten do paměti, ale zatímco se to děje, vyhledávání je úspěšné a lze provádět závislou práci a pokud části souboru nejsou ve skutečnosti nikdy potřeba, nečtou se (umožňují granularitu diskových a paměťových stránek a že i při použití mapování paměti vám mnoho operačních systémů umožňuje specifikovat některé tipy pro zvýšení výkonu/účinnosti paměti o vašem plánovaném přístup k vzorcům, aby mohli proaktivně číst dopředu nebo uvolnit paměť agresivněji s vědomím, že se k ní pravděpodobně nevrátíte). -
naprostá pravda
-
„Mapovaná oblast není sekvenční“ je vágní. Oblasti mapované do paměti jsou ve virtuálním adresovém prostoru „souvislé“ (sekvenční). Výše jsme diskutovali o sekvenčním vstupu/výstupu disku. Nebo myslíš na něco jiného? Každopádně, když jsou stránky poškozeny, mohou být skutečně přeneseny pomocí DMA.
Kromě toho existují další důvody, proč může mapování paměti překonat obvyklé I/O:
- je méně kopírování:
- často procházejí rutiny na úrovni operačního systému a knihovny data přes jednu nebo více vyrovnávacích pamětí, než se dostanou do vyrovnávací paměti určené aplikací, aplikace poté dynamicky přidělí úložiště a poté zkopíruje z vyrovnávací paměti I/O do tohoto úložiště, aby byla data použitelná po souboru čtení je dokončeno
- mapování paměti umožňuje (ale nevynucuje) použití na místě (stačí zaznamenat ukazatel a případně délku)
- pokračování v přístupu k datům na místě riskuje, že dojde k větším chybám mezipaměti a/nebo záměně později:soubor/mapa paměti by mohla být podrobnější než datové struktury, do kterých by mohla být analyzována, takže vzory přístupu k datům v nich mohou mít větší zpoždění zavinit více paměťových stránek
- mapování paměti může aplikaci zjednodušit úlohu analýzy tím, že aplikaci umožní, aby s celým obsahem souboru zacházela jako s přístupným, místo aby se starala o to, kdy načíst další vyrovnávací paměť plnou.
- Aplikace se více podřizuje moudrosti operačního systému, pokud jde o počet stránek, které jsou ve fyzické paměti RAM v libovolném okamžiku, a efektivně sdílí mezipaměť disku s přímým přístupem s aplikací
- stejně jako níže uvedené komentáře příznivců:„při použití mapování paměti obvykle spotřebováváte méně systémových volání“
- Pokud ke stejnému souboru přistupuje více procesů, měly by být schopny sdílet fyzické podkladové stránky
To jsou také důvody, proč mmap
může být pomalejší – přečtěte si zde příspěvek Linuse Torvalda, který říká mmap
:
...stránkové stolní hry spolu s chybou (a dokonce i jen chybou TLB) jsou snadno vyšší než náklady na zkopírování stránky pěkným streamovacím způsobem...
A z dalšího jeho příspěvku:
- poměrně znatelné náklady na nastavení a demontáž. A myslím pozoruhodný . Jsou to věci, jako je sledování tabulek stránek, abyste vše čistě odmapovali. Je to účetnictví pro vedení seznamu všech mapování. Je to TLB flush potřebný po odmapování věcí.
- chybování stránek je drahé. Takto se mapování vyplní a je to docela pomalé.
Linux má „obrovské stránky“ (takže jeden záznam TLB na 2 MB místo na 4 kb) a dokonce Transparent obrovské stránky, kde se je operační systém pokouší použít, i když kód aplikace nebyl napsán tak, aby je explicitně využíval.
FWIW, když se mi to naposledy vyskytlo v práci, vstup mapovaný do paměti byl o 80 % rychlejší než fread
et al pro čtení binárních databázových záznamů do proprietární databáze na 64bitovém Linuxu se soubory ~170 GB.
mmap()
může sdílet mezi procesy.- DMA bude použito, kdykoli to bude možné. DMA nevyžaduje souvislou paměť – mnoho špičkových karet podporuje DMA s rozptylovým sběrem.
- Pokud je to možné, může být oblast paměti sdílena s mezipamětí bloků jádra. Existuje tedy kopírování pronajímatelem.
- Paměť pro
mmap
je přidělen jádrem, je vždy zarovnán.