HugePages'i eelised ja puudused

HugePages'i eelised ja puudused

Artikli tõlge on ette valmistatud OTUS kursuse üliõpilaste jaoks. „Linuxi administraator“.

Varem rääkisin sellest, kuidas kontrollida ja lubada Hugepages kasutamist Linuxis.
See artikkel on kasulik ainult siis, kui teil on tõeliselt vajalik kasutada Hugepages. Olen kohtunud paljude inimestega, kes petavad end Hugepages'i lootuse peale, et need maagiliselt parandavad jõudlust. Sellegipoolest on hugepaging keeruline teema ja vale kasutamise korral võib see jõudlust hoopis vähendada.

Osa 1: kontrollige, et hugepages on Linuxis lubatud (originaal siit)

Probleem:
On vaja kontrollida, kas HugePages on teie süsteemis lubatud.

Lahenduseks on:
See on üsna lihtne:

cat /sys/kernel/mm/transparent_hugepage/enabled

Saate midagi sellist:

always [madvise] never

Käärid loetelu saadaval olevatest valikutest (always, madvise, never), samal ajal kui praegune aktiivne valik on sulgudes (vaikimisi madvise).

madvise tähendab, et tähendab, et transparent hugepages on lubatud ainult mälupiirkondades, mis nõuavad selgelt hugepages'i läbi.

always tähendab, et tähendab, et madvise(2)

kunagi tähendab, et tähendab, et ei aktiveerita isegi madvise käsu kaudu tehtud päringu korral. Lisainfot leiate dokumentatsioonis Linuxi tuumast.

Kuidas muuta vaikeseade

Valik 1: Muutke otse sysfs (pärast taaskäivitamist naaseb seade vaikeseadele):

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

Variant 2: Muutke vaikimisi süsteemiväärtust tuuma ümberkompileerimisega muudetud konfiguratsiooniga (see variant on soovitatav ainult siis, kui kasutate oma tuuma):

  • Et seadistada always vaikeseade, kasutage:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Kommenteerige välja CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Et seadistada madvise vaikeseade, kasutage:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Kommenteerige välja CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Osa 2: HugePages'i eelised ja puudused

Püüame seletada Hugepages'i kasutamise eeliseid, puudusi ja võimalikke vigu. Kuna tehniliselt keeruline ja pedantselt kirjutatud artikkel võib olla raskesti mõistetav neile, kes ekslikult arvavad, et Hugepages on imerohi, ohverdan ma täpsuse lihtsuse nimel. Oluline on meeles pidada, et paljud teemad on tõeliselt keerulised ja seetõttu tugevalt liialdatud.

Pange tähele, et räägime 64-bitistest x86 süsteemidest, mis töötavad Linuxil, ning ma lihtsalt eeldan, et süsteem toetab transparent hugepages'i (sest Hugepages'i mitte vahetamine ei ole puuduseks), nagu see on peaaegu kõigis kaasaegsetes Linuxi keskkondades.

Allpool olevates linkides jagan rohkem tehnilist kirjeldust.

Virtuaalne mälu

Kui olete C++ programmeerija, siis tead, et objektidel mälus on konkreetsed aadressid (punkti väärtused).

Kuid need aadressid ei peegelda tingimata füüsilisi aadresse mälus (RAM aadresse). Need esindavad aadresse virtuaalses mälus. Protsessoril on spetsiaalne MMU (memory management unit), mis aitab tuumal sobitada virtuaalset mälu füüsilise asukohaga.

Sellel lähenemisel on mitmeid eeliseid, kuid peamised on järgmised:

  • Tõhusus (erinevatel põhjustel);
  • Programmide isoleerimine, st ükski programm ei saa lugeda teise programmi mälust.

Mis on lehed?

Virtuaalne mälu on jagatud lehtedeks. Iga eraldi leht viitab kindlale füüsilisele mälule, see võib viidata alale RAM-is või aadressile, mis on määratud füüsilisele seadmele, näiteks graafikakaardile.

Enamik lehti, millega te tegelete, osutavad kas RAM-i või vahetusfailile (swap), st nad on salvestatud kõvakettale või SSD-le. Südamik haldab iga lehe füüsilist asukohta. Kui vahetuslehele juurdepääs on vajalik, peatab südamik selle voolu, mis püüab mällu pääseda, loeb lehe kõvakettalt/SSD-lt RAM-i ja jätkab seejärel voolu täitmist.

See protsess on voolu jaoks läbipaistev, see tähendab, et see ei pea tingimata otse kõvakettalt/SSD-lt lugema. Tavaline lehe suurus on 4096 baiti. Hugepage'i suurus on 2 megabaiti.

Assotsiatiivse tõlke puu (TLB)

Kui programm pöördub teatud mälulehe poole, peab protsessor teadma, milliselt füüsiliselt lehelt andmeid lugeda (st tal peab olema virtuaalne aadressikaart).

Südamikus on andmestruktuur (lehekülgede tabel), mis sisaldab kõiki teavet kasutatavate lehtede kohta. Selle andmestruktuuri abil saab virtuaalse aadressi füüsilise aadressiga siduda.

Kuid leheküljed on üsna keerulised ja töötavad aeglaselt, seega me ei saa andmestruktuuri alati analüüsida, kui mõni protsess mälu juurde pääseb.

Õnneks on meie protsessoris TLB, mis vahemälustab virtuaal- ja füüsiliste aadresside vasteid. See tähendab, et kuigi me peame leheküljete tabelit analüüsima esimesel pääsul, saavad kõik järgmised leheküljed töötlemiseks kasutada TLB-d, mis tagab kiire toimimise.

Kuna see on füüsilise seadmena rakendatud (mis teeb selle eelkõige kiireks), on selle maht piiratud. Seetõttu, kui soovite juurde pääseda suuremale hulgale lehekülgedele, ei suuda TLB neid kõiki salvestada, mille tõttu teie programm töötab palju aeglasemalt.

Hugepages tulevad appi

Nii et mida me saame teha TLB ületäitumise vältimiseks? (Eeldame, et programm vajab endiselt sama palju mälu).

Siin tulevadki mängu Hugepages. Selle asemel, et kasutada 4096 baiti, mis vajavad vaid ühte sissekannet TLB-s, võib nüüd üks sissekanne TLB-s viidata hiiglaslikele 2 megabaitidele. Oletame, et TLB-s on 512 sissekannet, siis ilma Hugepages'te kasutamiseta saame seondada:

4096 b⋅512=2 MB

Kuid nendega saame seondada:

2 MB⋅512=1 GB

Seetõttu on Hugepages nii ägedad. Need võivad suurendada jõudlust ilma põhjapaneva vaevata. Kuid siin on olulised erandid.

Hugepages'i asendamine

Tuuma jälgib automaatselt iga mälu lehe kasutamise sagedust. Kui füüsilisest mälust (RAM) ei piisa, liigutab tuum vähem olulised (harvemini kasutatavad) lehed kõvakettale, et vabastada natuke RAM-i olulisematele lehtedele.
Põhimõtteliselt kehtib sama ka Hugepages'i kohta. Kuid tuum saab vahetada ainult terveid lehti, mitte üksikuid bite.

Oletame, et meil on selline programm:

char* mymemory = malloc(2*1024*1024); // Võtame selle ühe Hugepage'ina!
// Täidame mymemory mingi andmetega
// Teeme palju muid asju,
// mis viivad mymemory lehe asendamiseni
// ...
// Küsimise sissepääsu ainult esimesse bite
putchar(mymemory[0]); 

Selle puhul peab tuuma lugema kõiki 2 megabaiti teavet kõvakettalt/SSD-lt, et lugeda üks bait. Tavaliste lehtede puhul tuleb lugeda kõvakettalt/SSD-lt vaid 4096 baiti.

Seetõttu, kui hugepage asendatakse, toimub selle lugemine kiiremini, kui peate juurde pääsema tervele lehele. See tähendab, et kui proovite juhuslikult pääseda juurde erinevatele mälupiirkondadele ja lihtsalt lugeda paar kilobaiti, peaksite kasutama tavalisi lehti ja mitte millelegi muule muret tundma.

Teisest küljest, kui peate järjestikuse juurdepääsu suurele mäluhulgale, suurendavad hugepages teie jõudlust. Siiski peate seda ise kontrollima (mitte abstraktse tarkvara näitel) ja vaatama, mis töötab kiiremini.

Mälu eraldamine

Kui kirjutate C-s, teate, et saate taotleda peaaegu piiramatu (või peaaegu piiramatu) mälu hulga eraldamist virnast, kasutades malloc(). Oletame, et teil on vaja 30 baiti mälu:

char* mymemory = malloc(30);

Programmeerijale võib tunduda, et te "küsite" 30 baiti mälu operatsioonisüsteemist ja tagastate viite mõnesse virtuaalmälu. Kuid tegelikult malloc() on lihtsalt C-funktsioon, mis kutsub seespool funktsioone brk ja sbrk mälu taotlemiseks või vabastamiseks operatsioonisüsteemist.

Kuid pidevalt rohkem ja rohkem mälu taotlemine iga allocatsiooni jaoks ei ole tõhus; on tõenäoliselt, et mingi mälu segment on juba vabastatud (free()), ja me saame seda uuesti kasutada. malloc() rakendab üsna keerulisi algoritme vabastatud mälu taaskasutamiseks.

Samal ajal toimub see teie jaoks märkamatult, miks see peaks muret tekitama? Just sellepärast, et väljakutse free() ei tähenda, et mälu peab kohe olema tagasi operatsioonisüsteemile.

Mälu fragmenteerumise mõisted on olemas. Äärmuslikel juhtudel on olemas kuhjade segmendid, kus kasutatakse ainult mõnda baiti, samas kui kõik, mis nende vahel on, on vabastatud. (free()).

Pange tähele, et mälu fragmenteerimine on äärmiselt keeruline teema ning isegi väikesed muudatused programmis võivad sellel oluliselt mõju avaldada. Enamasti ei põhjusta programmid küllaldast mälu fragmenteerimist, kuid peate meeles pidama, et kui mingis piirkonnas on tekkimas mälufragmenteerimise probleem, siis hugepages võivad olukorda ainult halvendada.

Valikuline hugepages'i rakendamine

Pärast artikli lugemist olete määranud, millised teie programmi osad saavad hugepages'i rakendamisest kasu ja millised ei saa. Kas tasuks hugepages'id üldse sisse lülitada?

Õnneks saate kasutada madvise(), et lubada hugepaging ainult neis mälu piirkondades, kus see oleks kasulik.

Esiteks, kontrollige, kas hugepages töötavad madvise() režiimis, kasutades juhendis artikli alguses.

Seejärel kasutage madvise(), et öelda tuumale, kus täpselt hugepages'e kasutada.

#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)

Pange tähele, et see meetod - lihtsalt soovitus tuumale mälu haldamiseks. See ei tähenda, et tuum hakkaks automaatselt hugepages'e antud mälu jaoks kasutama.

Konsulteerige dokumentatsiooniga (manpage) madvise, et saada rohkem teavet mälu haldamise kohta ja madvise(), selle teema õppimiskõver on uskumatu. Seetõttu, kui kavatsete sellest tõeliselt hästi aru saada, valmistuge lugema ja katsetama mitu nädalat, enne kui loodate mõningaid positiivseid tulemusi.

Mida lugeda?

On küsimusi? Kirjutage kommentaaridesse!

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster