Výhody a nevýhody HugePages

Výhody a nevýhody HugePages

Překlad článku připraveného pro studenty kurzu "Správce Linuxu".

Dříve jsem mluvil o tom, jak testovat a povolit Hugepages v Linuxu.
Tento článek bude užitečný pouze v případě, že skutečně máte kde používat Hugepages. Setkal jsem se s mnoha lidmi, kteří jsou oklamáni vyhlídkou, že Hugepages magicky zlepší produktivitu. Obrovské stránkování je však složité téma a při nesprávném použití může snížit výkon.

Část 1: Ověření, že jsou v systému Linux povoleny hugepages (originál zde)

Problém:
Musíte zkontrolovat, zda je ve vašem systému povolena služba HugePages.

řešení:
Je to docela jednoduché:

cat /sys/kernel/mm/transparent_hugepage/enabled

Dostanete něco takového:

always [madvise] never

Zobrazí se seznam dostupných možností (vždy, blázen, nikdy) a aktuálně aktivní možnost bude uzavřena v závorkách (ve výchozím nastavení šílený).

šílený znamená, že transparent hugepages povoleno pouze pro oblasti paměti, které explicitně vyžadují použití velkých stránek šíleně (2).

vždy znamená, že transparent hugepages vždy povoleno pro všechny procesy. To obvykle zlepšuje výkon, ale pokud máte případ použití, kdy mnoho procesů spotřebovává malé množství paměti, může se celkové zatížení paměti dramaticky zvýšit.

nikdy znamená, že transparent hugepages nebudou zahrnuty ani na vyžádání pomocí madvise. Chcete-li se dozvědět více, kontaktujte dokumentace Linuxová jádra.

Jak změnit výchozí hodnotu

Možnost 1: Přímá změna sysfs (po restartu se parametr vrátí na výchozí hodnotu):

echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled

Možnost 2: Změňte výchozí nastavení systému překompilováním jádra s upravenou konfigurací (tato možnost se doporučuje pouze v případě, že používáte vlastní jádro):

  • Chcete-li jako výchozí nastavit vždy, použijte:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Chcete-li nastavit madvise jako výchozí, použijte:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Část 2: Výhody a nevýhody HugePages

Pokusíme se výběrově vysvětlit výhody, nevýhody a možná úskalí používání Hugepages. Vzhledem k tomu, že technologicky složitý a pedantský článek bude pravděpodobně obtížné pochopit pro lidi, kteří si myslí, že Hugepages je všelék, obětuji přesnost kvůli jednoduchosti. Jen stojí za to mít na paměti, že spousta témat je opravdu složitých, a proto značně zjednodušených.

Vezměte prosím na vědomí, že mluvíme o 64bitových x86 systémech s Linuxem a že jednoduše předpokládám, že systém podporuje transparentní hugepages (protože není nevýhodou, že se hugepages nepřepisují), jako je tomu v téměř každém moderním Linuxu životní prostředí.

Další technický popis přiložím v odkazech níže.

Virtuální paměť

Pokud jste programátor v C++, víte, že objekty v paměti mají specifické adresy (hodnoty ukazatelů).

Tyto adresy však nemusí nutně odrážet fyzické adresy v paměti (adresy RAM). Představují adresy ve virtuální paměti. Procesor má speciální modul MMU (memory management unit), který pomáhá jádru mapovat virtuální paměť na fyzické umístění.

Tento přístup má mnoho výhod, ale ty nejdůležitější jsou:

  • Výkon (z různých důvodů);
  • Izolace programu, to znamená, že žádný program nemůže číst z paměti jiného programu.

Co jsou stránky?

Virtuální paměť je rozdělena na stránky. Každá jednotlivá stránka ukazuje na určitou fyzickou paměť, může ukazovat na oblast v paměti RAM nebo může ukazovat na adresu přiřazenou fyzickému zařízení, jako je grafická karta.

Většina stránek, se kterými se zabýváte, odkazuje buď na RAM, nebo jsou prohozené, což znamená, že jsou uloženy na vašem pevném disku nebo SSD. Jádro spravuje fyzické rozvržení každé stránky. Dojde-li k přístupu na podvrženou stránku, jádro zastaví vlákno, které se pokouší o přístup k paměti, načte stránku z pevného disku/SSD do RAM a poté pokračuje ve spouštění vlákna.

Tento proces je transparentní, což znamená, že nemusí nutně číst přímo z HDD/SSD. Velikost normálních stránek je 4096 bajtů. Obrovská velikost stránek je 2 MB.

Překlad-asociativní vyrovnávací paměť (TLB)

Když program přistupuje na stránku paměti, CPU musí vědět, ze které fyzické stránky má číst data (tj. mít mapu virtuální adresy).

Jádro má datovou strukturu (tabulku stránek), která obsahuje všechny informace o používaných stránkách. Pomocí této datové struktury můžete mapovat virtuální adresu na fyzickou adresu.

Tabulka stránek je však poměrně složitá a pomalá, takže prostě nemůžeme analyzovat celou datovou strukturu pokaždé, když proces přistupuje k paměti.

Náš procesor má naštěstí TLB, která ukládá do mezipaměti mapování mezi virtuálními a fyzickými adresami. To znamená, že i když potřebujeme analyzovat tabulku stránek při prvním pokusu o přístup, všechny následné přístupy ke stránce lze zpracovat v TLB, což umožňuje rychlý provoz.

Protože je implementován jako fyzické zařízení (což jej činí především rychlým), jeho kapacita je omezená. Pokud tedy chcete přistupovat k více stránkám, TLB nebude moci ukládat mapování pro všechny z nich, což způsobí, že váš program poběží mnohem pomaleji.

Hugepages přichází na pomoc

Co tedy můžeme udělat, abychom se vyhnuli přetečení TLB? (Předpokládáme, že program potřebuje stále stejné množství paměti).

Zde přichází na řadu Hugepages. Namísto 4096 bajtů vyžadujících pouze jeden záznam TLB může nyní jeden záznam TLB ukazovat na ohromné ​​2 megabajty. Předpokládejme, že TLB má 512 záznamů, zde bez Hugepages můžeme porovnávat:

4096 b⋅512=2 MB

Jak se s nimi tedy můžeme srovnávat:

2 MB⋅512=1 GB

To je důvod, proč jsou Hugepages úžasné. Mohou zvýšit produktivitu bez velkého úsilí. Ale jsou zde významné výhrady.

Spoofing obrovských stránek

Jádro automaticky sleduje, jak často jsou jednotlivé stránky paměti využívány. Pokud není dostatek fyzické paměti (RAM), jádro přesune méně důležité (méně často používané) stránky na pevný disk, aby uvolnilo RAM pro důležitější stránky.
V zásadě to samé platí pro Hugepages. Jádro však může zaměňovat pouze celé stránky, nikoli jednotlivé bajty.

Řekněme, že máme program jako tento:

char* mymemory = malloc(2*1024*1024); // Возьмем это за одну Hugepage!
// Заполним mymemory какими-либо данными
// Сделаем много других вещей,
// которые приведут к подмене страницы mymemory
// ...
// Запросим доступ только к первому байту
putchar(mymemory[0]); 

V tomto případě bude jádro muset nahradit (přečíst) až 2 megabajty informací z pevného disku/SSD, abyste mohli přečíst jeden bajt. Pokud jde o běžné stránky, z pevného disku/SSD stačí přečíst pouze 4096 bajtů.

Pokud je tedy obrovská stránka přepsána, je čtení rychlejší pouze v případě, že potřebujete získat přístup k celé stránce. To znamená, že pokud se pokoušíte náhodně přistupovat k různým částem paměti a čtete jen několik kilobajtů, měli byste používat běžné stránky a nestarat se o nic jiného.

Na druhou stranu, pokud potřebujete přistupovat k velké části paměti postupně, obrovské stránky zlepší váš výkon. Musíte to však vyzkoušet sami (nikoli s abstraktním softwarem) a zjistit, co funguje rychleji.

Alokace v paměti

Pokud napíšete C, víte, že můžete požadovat libovolně malé (nebo téměř libovolně velké) množství paměti z haldy pomocí malloc(). Řekněme, že potřebujete 30 bajtů paměti:

char* mymemory = malloc(30);

Programátorovi se může zdát, že od operačního systému „požadujete“ 30 bajtů paměti a vracíte ukazatel na nějakou virtuální paměť. Ale opravdu malloc () je pouze funkce C, která volá zevnitř funkce brk a sbrk vyžádat nebo uvolnit paměť z operačního systému.

Požadování stále více paměti pro každou alokaci je však neefektivní; je velmi pravděpodobné, že některý segment paměti již byl uvolněn (free())a můžeme jej znovu použít. malloc() implementuje poměrně složité algoritmy pro opětovné použití uvolněné paměti.

Vše se vám přitom děje nepozorovaně, tak proč by vás to mělo znepokojovat? Ale protože výzva free() to neznamená paměť je nutně okamžitě vrácena operačnímu systému.

Existuje něco jako fragmentace paměti. V extrémních případech existují segmenty haldy, kde se používá pouze několik bajtů, zatímco vše mezi tím bylo uvolněno (free()).

Upozorňujeme, že fragmentace paměti je neuvěřitelně složité téma a i drobné změny v programu mohou mít významný dopad. Ve většině případů programy nezpůsobí významnou fragmentaci paměti, ale měli byste si být vědomi toho, že pokud dojde k problému s fragmentací v některé oblasti haldy, mohou velké stránky situaci zhoršit.

Selektivní použití velkých stránek

Po přečtení tohoto článku jste určili, které části vašeho programu mohou mít z používání hugepages prospěch a které nikoli. Měly by tedy být hugepages vůbec povoleny?

Naštěstí můžete použít madvise()povolit obrovské stránkování pouze pro ty oblasti paměti, kde by to bylo užitečné.

Nejprve zkontrolujte, že hugepages běží v režimu madvise() pomocí instrukce na začátku článku.

Poté použijte madvise()říct jádru, kde přesně má používat hugepages.

#include <sys/mman.h>
// Аллоцируйте большое количество памяти, которую будете использовать
size_t size = 256*1024*1024;
char* mymemory = malloc(size);
// Просто включите hugepages…
madvise(mymemory, size, MADV_HUGEPAGE);
// … и задайте следующее
madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)

Všimněte si, že tato metoda je pouze rada pro jádro, jak spravovat paměť. To neznamená, že jádro automaticky použije pro danou paměť obrovské stránky.

Viz dokumentace (manpage)madvisese dozvíte více o správě paměti a madvise(), toto téma má neuvěřitelně strmou křivku učení. Pokud tedy máte v úmyslu se v tom opravdu zdokonalit, připravte se na čtení a testování několik týdnů, než budete očekávat nějaké pozitivní výsledky.

co číst?

Mít dotaz? Pište do komentářů!

Zdroj: www.habr.com

Přidat komentář