GNU/Linux >> Znalost Linux >  >> Linux

Proč je mmap() rychlejší než sekvenční IO?

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.

  1. 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é?

  1. 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, pak mmap 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).

  2. naprostá pravda

  3. „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.


  1. mmap() může sdílet mezi procesy.
  2. 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.
  3. 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.
  4. Paměť pro mmap je přidělen jádrem, je vždy zarovnán.

Linux
  1. Proč je Windows10 VM pomalý na OpenStack?

  2. Proč je scp tak pomalý a jak jej urychlit?

  3. Sdílená paměť Linuxu:shmget() vs mmap()?

  1. Proč používat shm_open?

  2. Proč malloc() volá mmap() a brk() zaměnitelně?

  3. Proč je sdílená paměť jádra na Ubuntu 12.04 0?

  1. Proč je Printf lepší než Echo?

  2. ZFS pool pomalé sekvenční čtení

  3. Proč se heslo 'sudo' liší od hesla 'su root'