Výhody a nevýhody HugePages

Výhody a nevýhody HugePages

Preklad článku pripraveného pre študentov kurzu "Správca Linuxu".

Predtým som hovoril o tom, ako testovať a povoliť Hugepages v systéme Linux.
Tento článok bude užitočný iba vtedy, ak skutočne máte miesto na používanie Hugepages. Stretol som veľa ľudí, ktorí sú oklamaní predstavou, že Hugepages zázračne zvýši produktivitu. Obrovské stránkovanie je však zložitá téma a pri nesprávnom použití môže znížiť výkon.

Časť 1: Overenie, či sú v systéme Linux povolené obrovské stránky (originál tu)

Problém:
Musíte skontrolovať, či je vo vašom systéme povolená služba HugePages.

riešenie:
Je to celkom jednoduché:

cat /sys/kernel/mm/transparent_hugepage/enabled

Dostanete niečo takéto:

always [madvise] never

Zobrazí sa zoznam dostupných možností (vždy, blázon, nikdy) a aktuálne aktívna možnosť bude uzavretá v zátvorkách (predvolene madvis).

madvis znamená to transparent hugepages povolené len pre oblasti pamäte, ktoré explicitne vyžadujú použitie veľkých stránok madvise (2).

vždy znamená to transparent hugepages vždy povolené pre všetky procesy. To zvyčajne zlepšuje výkon, ale ak máte prípad použitia, keď mnohé procesy spotrebúvajú malé množstvo pamäte, celkové zaťaženie pamäte sa môže dramaticky zvýšiť.

nikdy znamená to transparent hugepages nebudú zahrnuté, ani keď sa o to požiada pomocou madvise. Ak sa chcete dozvedieť viac, kontaktujte dokumentáciu Linuxové jadrá.

Ako zmeniť predvolenú hodnotu

Možnosť 1: Priama zmena sysfs (po reštarte sa parameter vráti na predvolenú 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žnosť 2: Zmeňte predvolené nastavenie systému opätovnou kompiláciou jadra s upravenou konfiguráciou (táto možnosť sa odporúča iba vtedy, ak používate vlastné jadro):

  • Ak chcete nastaviť vždy predvolene, použite:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Ak chcete nastaviť madvise ako predvolené, použite:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Časť 2: Výhody a nevýhody HugePages

Pokúsime sa selektívne vysvetliť výhody, nevýhody a možné úskalia používania Hugepages. Keďže technologicky zložitý a pedantský článok bude pravdepodobne ťažko pochopiteľný pre ľudí, ktorí si myslia, že Hugepages je všeliek, obetujem presnosť kvôli jednoduchosti. Len stojí za to mať na pamäti, že veľa tém je skutočne zložitých, a preto značne zjednodušených.

Upozorňujeme, že hovoríme o 64-bitových x86 systémoch s Linuxom a že jednoducho predpokladám, že systém podporuje transparentné obrovské stránky (keďže nie je nevýhodou, že sa obrovské stránky neprepisujú), ako je to v prípade takmer každého moderného Linuxu životné prostredie.

Podrobnejší technický popis pripojím v odkazoch nižšie.

Virtuálna pamäť

Ak ste programátor v C++, viete, že objekty v pamäti majú špecifické adresy (hodnoty ukazovateľov).

Tieto adresy však nemusia nevyhnutne odrážať fyzické adresy v pamäti (adresy RAM). Predstavujú adresy vo virtuálnej pamäti. Procesor má špeciálny modul MMU (memory management unit), ktorý pomáha jadru mapovať virtuálnu pamäť na fyzické miesto.

Tento prístup má mnoho výhod, ale tie najdôležitejšie sú:

  • Výkon (z rôznych dôvodov);
  • Programová izolácia, to znamená, že žiadny program nemôže čítať z pamäte iného programu.

Čo sú stránky?

Virtuálna pamäť je rozdelená na stránky. Každá jednotlivá stránka ukazuje na konkrétnu fyzickú pamäť, môže ukazovať na oblasť v RAM alebo môže ukazovať na adresu priradenú fyzickému zariadeniu, ako je napríklad grafická karta.

Väčšina stránok, s ktorými sa zaoberáte, smeruje buď do pamäte RAM, alebo sú vymenené, čo znamená, že sú uložené na pevnom disku alebo SSD. Jadro spravuje fyzické rozloženie každej stránky. Ak dôjde k prístupu na falošnú stránku, jadro zastaví vlákno, ktoré sa pokúša o prístup k pamäti, načíta stránku z pevného disku/SSD do pamäte RAM a potom pokračuje vo vykonávaní vlákna.

Tento proces je transparentný, čo znamená, že nemusí nutne čítať priamo z HDD/SSD. Veľkosť bežných stránok je 4096 bajtov. Obrovská veľkosť stránok je 2 megabajty.

Preklad-asociačná vyrovnávacia pamäť (TLB)

Keď program pristupuje na stránku pamäte, CPU musí vedieť, z ktorej fyzickej stránky má čítať dáta (to znamená mať mapu virtuálnej adresy).

Jadro má dátovú štruktúru (tabuľka stránok), ktorá obsahuje všetky informácie o používaných stránkach. Pomocou tejto dátovej štruktúry môžete mapovať virtuálnu adresu na fyzickú adresu.

Tabuľka stránok je však pomerne zložitá a pomalá, takže jednoducho nemôžeme analyzovať celú dátovú štruktúru zakaždým, keď proces pristupuje k pamäti.

Našťastie náš procesor má TLB, ktorá ukladá do vyrovnávacej pamäte mapovanie medzi virtuálnymi a fyzickými adresami. To znamená, že hoci potrebujeme analyzovať tabuľku stránok pri prvom pokuse o prístup, všetky následné prístupy na stránku je možné spracovať v TLB, čo umožňuje rýchlu prevádzku.

Keďže je implementovaný ako fyzické zariadenie (čo ho robí predovšetkým rýchlym), jeho kapacita je obmedzená. Ak teda chcete pristupovať k viacerým stránkam, TLB nebude môcť ukladať mapovania pre všetky z nich, čo spôsobí, že váš program bude bežať oveľa pomalšie.

Hugepages prichádza na záchranu

Čo teda môžeme urobiť, aby sme sa vyhli pretečeniu TLB? (Predpokladáme, že program potrebuje stále rovnaké množstvo pamäte).

Tu prichádza na rad Hugepages. Namiesto 4096 bajtov vyžadujúcich len jeden záznam TLB, jeden záznam TLB teraz môže ukazovať na obrovské 2 megabajty. Predpokladajme, že TLB má 512 záznamov, tu bez obrovských stránok môžeme porovnávať:

4096 b⋅512=2 MB

Ako sa s nimi potom môžeme porovnávať:

2 MB⋅512=1 GB

To je dôvod, prečo sú Hugepages úžasné. Môžu zvýšiť produktivitu bez veľkého úsilia. Ale sú tu významné výhrady.

Obrovské spoofingy

Jadro automaticky sleduje, ako často sa používa každá pamäťová stránka. Ak nie je dostatok fyzickej pamäte (RAM), jadro presunie menej dôležité (menej často používané) stránky na pevný disk, aby uvoľnilo RAM pre dôležitejšie stránky.
V zásade to isté platí pre Hugepages. Jadro však dokáže zamieňať iba celé stránky, nie jednotlivé bajty.

Povedzme, že máme takýto program:

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

V tomto prípade bude jadro musieť nahradiť (prečítať) až 2 megabajty informácií z pevného disku/SSD, aby ste mohli prečítať jeden bajt. Pokiaľ ide o bežné stránky, z pevného disku/SSD je potrebné prečítať iba 4096 bajtov.

Preto, ak je obrovská stránka prepísaná, je čítanie rýchlejšie iba vtedy, ak potrebujete získať prístup k celej stránke. To znamená, že ak sa pokúšate o náhodný prístup k rôznym častiam pamäte a práve čítate niekoľko kilobajtov, mali by ste používať bežné stránky a nestarať sa o nič iné.

Na druhej strane, ak potrebujete pristupovať k veľkej časti pamäte postupne, obrovské stránky zlepšia váš výkon. Musíte to však otestovať sami (nie s abstraktným softvérom) a zistiť, čo funguje rýchlejšie.

Pridelenie v pamäti

Ak napíšete C, viete, že môžete požadovať ľubovoľne malé (alebo takmer ľubovoľne veľké) množstvo pamäte z haldy pomocou malloc(). Povedzme, že potrebujete 30 bajtov pamäte:

char* mymemory = malloc(30);

Programátorovi sa môže zdať, že od operačného systému „požadujete“ 30 bajtov pamäte a vraciate ukazovateľ na nejakú virtuálnu pamäť. Ale vlastne malloc () je len funkcia C, ktorá volá zvnútra funkcie brk a sbrk vyžiadať alebo uvoľniť pamäť z operačného systému.

Požadovanie viac a viac pamäte pre každú alokáciu je však neefektívne; je najpravdepodobnejšie, že niektorý segment pamäte už bol uvoľnený (free())a môžeme ho znova použiť. malloc() implementuje pomerne zložité algoritmy na opätovné použitie uvoľnenej pamäte.

Zároveň sa pre vás všetko deje nepozorovane, tak prečo by vás to malo znepokojovať? Ale preto, že výzva free() to neznamená pamäť sa nevyhnutne okamžite vráti do operačného systému.

Existuje niečo ako fragmentácia pamäte. V extrémnych prípadoch existujú segmenty haldy, kde sa používa iba niekoľko bajtov, zatiaľ čo všetko medzi tým bolo uvoľnené (free()).

Upozorňujeme, že fragmentácia pamäte je neuveriteľne zložitá téma a dokonca aj malé zmeny v programe môžu mať významný vplyv. Vo väčšine prípadov programy nespôsobia významnú fragmentáciu pamäte, ale mali by ste si uvedomiť, že ak sa vyskytne problém s fragmentáciou v niektorej oblasti haldy, obrovské stránky môžu situáciu zhoršiť.

Selektívne použitie veľkých stránok

Po prečítaní tohto článku ste sa rozhodli, ktoré časti vášho programu môžu využívať výhody používania hugepages a ktoré nie. Mali by byť teda hugepages vôbec povolené?

Našťastie môžete použiť madvise()povoliť obrovské stránkovanie len pre tie oblasti pamäte, kde by to bolo užitočné.

Najprv skontrolujte, či hugepages beží v režime madvise() pomocou inštrukcie na začiatku článku.

Potom použite madvise()povedať jadru, kde presne má používať 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šimnite si, že táto metóda je len rada pre jadro, ako spravovať pamäť. To neznamená, že jadro automaticky použije pre danú pamäť obrovské stránky.

Pozrite si dokumentáciu (manpage)madvisesa dozviete viac o správe pamäte a madvise(), táto téma má neuveriteľne strmú krivku učenia. Takže ak máte v úmysle byť v tom naozaj dobrí, pripravte sa na čítanie a testovanie niekoľko týždňov, než budete očakávať nejaké pozitívne výsledky.

čo čítať?

Mať otázku? Napíšte do komentárov!

Zdroj: hab.com

Pridať komentár