HugePagesi eelised ja puudused

HugePagesi eelised ja puudused

Kursuse üliõpilastele koostatud artikli tõlge "Linuxi administraator".

Eelnevalt rääkisin, kuidas Linuxis Hugepagesi testida ja lubada.
See artikkel on kasulik ainult siis, kui teil on tõesti koht, kus Hugepagesi kasutada. Olen kohanud paljusid inimesi, keda lollitab väljavaade, et Hugepages tõstab võluväel tootlikkust. Hiiglaslik lehekülg on aga keeruline teema ja võib ebaõige kasutamise korral jõudlust halvendada.

1. osa: kontrollige, kas suured lehed on Linuxis lubatud (originaal siin)

Probleem:
Peate kontrollima, kas teie süsteemis on HugePages lubatud.

lahendus:
See on üsna lihtne:

cat /sys/kernel/mm/transparent_hugepage/enabled

Saate midagi sellist:

always [madvise] never

Näete saadaolevate valikute loendit (alati, madvise, mitte kunagi) ja praegu aktiivne valik on sulgudes (vaikimisi hull).

hull tähendab seda transparent hugepages lubatud ainult nende mälupiirkondade jaoks, mis nõuavad selgesõnaliselt suuri lehti madvise (2).

alati tähendab seda transparent hugepages alati kõigi protsesside jaoks lubatud. Tavaliselt parandab see jõudlust, kuid kui teil on kasutusjuhtum, kus paljud protsessid tarbivad vähe mälu, võib üldine mälukoormus järsult suureneda.

mitte kunagi tähendab seda transparent hugepages ei lisata isegi siis, kui seda taotletakse madvise abil. Lisateabe saamiseks võtke ühendust dokumentatsioon Linuxi tuumad.

Kuidas muuta vaikeväärtust

Valik 1: Vahetu otse sysfs (pärast taaskäivitamist naaseb parameeter vaikeväärtusele):

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

Valik 2: Muutke süsteemi vaikeseadet, kompileerides kerneli muudetud konfiguratsiooniga (see valik on soovitatav ainult siis, kui kasutate kohandatud tuuma):

  • Alati vaikimisi määramiseks kasutage:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Madvise vaikeseadeks määramiseks kasutage:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

2. osa: HugePages'i eelised ja puudused

Püüame valikuliselt selgitada Hugepagesi kasutamise eeliseid, puudusi ja võimalikke lõkse. Kuna tehnoloogiliselt keerukat ja pedantset artiklit on tõenäoliselt raske mõista inimestel, kes arvavad, et Hugepages on imerohi, ohverdan lihtsuse nimel täpsuse. Tasub lihtsalt meeles pidada, et paljud teemad on tõesti keerulised ja seetõttu oluliselt lihtsustatud.

Pange tähele, et me räägime 64-bitistest x86 süsteemidest, mis käitavad Linuxit, ja ma lihtsalt eeldan, et süsteem toetab läbipaistvaid tohutuid lehti (kuna suurte lehtede ülekirjutamata jätmine pole puuduseks), nagu see on peaaegu iga kaasaegse Linuxi puhul. keskkond.

Lisan allolevatele linkidele täpsema tehnilise kirjelduse.

Virtuaalne mälu

Kui olete C++ programmeerija, siis teate, et mälus olevatel objektidel on kindlad aadressid (osutiväärtused).

Need aadressid ei pruugi aga kajastada füüsilisi aadresse mälus (RAM-aadressid). Need esindavad virtuaalmälus olevaid aadresse. Protsessoril on spetsiaalne MMU (memory management unit) moodul, mis aitab kernelil virtuaalmälu füüsilisse asukohta kaardistada.

Sellel meetodil on palju eeliseid, kuid kõige olulisemad on järgmised:

  • jõudlus (erinevatel põhjustel);
  • Programmi isoleerimine, st ükski programm ei saa lugeda teise programmi mälust.

Mis on lehed?

Virtuaalmälu on jagatud lehtedeks. Iga üksik leht osutab konkreetsele füüsilisele mälule, see võib osutada RAM-i alale või füüsilisele seadmele, näiteks videokaardile, määratud aadressile.

Enamik lehekülgi, millega te tegelete, osutavad RAM-ile või on vahetatud, mis tähendab, et need salvestatakse teie kõvakettale või SSD-le. Kernel haldab iga lehe füüsilist paigutust. Kui pääsete juurde võltsitud lehele, peatab kernel lõime, mis üritab mälule juurde pääseda, loeb lehe kõvakettalt/SSD-lt RAM-i ja jätkab seejärel lõime täitmist.

See protsess on voo läbipaistev, mis tähendab, et see ei pruugi lugeda otse HDD-lt/SSD-lt. Tavaliste lehtede suurus on 4096 baiti. Hiiglaslike lehtede suurus on 2 megabaiti.

Tõlke-assotsiatiivne puhver (TLB)

Kui programm avab mälulehe, peab CPU teadma, milliselt füüsiliselt lehelt andmeid lugeda (st omama virtuaalset aadressikaarti).

Kernelil on andmestruktuur (lehetabel), mis sisaldab kogu infot kasutatavate lehtede kohta. Seda andmestruktuuri kasutades saate virtuaalse aadressi vastendada füüsiliseks aadressiks.

Lehe tabel on aga üsna keeruline ja aeglane, mistõttu me lihtsalt ei saa analüüsida kogu andmestruktuuri iga kord, kui protsess mälule pöördub.

Õnneks on meie protsessoril TLB, mis salvestab virtuaalse ja füüsilise aadressi vahelise vastendamise vahemällu. See tähendab, et kuigi me peame lehe tabelit sõeluma esimesel juurdepääsukatsel, saab kõiki järgnevaid juurdepääsuid lehele käsitleda TLB-s, mis võimaldab kiiret toimimist.

Kuna see on rakendatud füüsilise seadmena (mis teeb selle esiteks kiireks), on selle võimsus piiratud. Nii et kui soovite juurde pääseda rohkematele lehtedele, ei saa TLB salvestada nende kõigi vastendusi, mistõttu teie programm töötab palju aeglasemalt.

Hugepages tuleb appi

Mida me saame teha, et vältida TLB ületäitumist? (Eeldame, et programm vajab endiselt sama palju mälu).

Siin tuleb mängu Hugepages. Selle asemel, et 4096 baiti vajaksid vaid ühte TLB-kirjet, võib üks TLB-kirje nüüd osutada ilmatu 2-megabaidile. Oletame, et TLB-l on 512 kirjet, siin saame ilma tohutute lehtedeta sobitada:

4096 b⋅512=2 MB

Kuidas saame siis nendega võrrelda:

2 MB⋅512=1 GB

Seetõttu on Hugepages suurepärane. Need võivad tootlikkust ilma suurema vaevata parandada. Kuid siin on olulisi hoiatusi.

Tohutute lehtede võltsimine

Kernel jälgib automaatselt, kui sageli iga mälulehte kasutatakse. Kui füüsilist mälu (RAM) pole piisavalt, liigutab kernel vähemtähtsad (harvemini kasutatavad) lehed kõvakettale, et vabastada osa RAM-i olulisemate lehtede jaoks.
Põhimõtteliselt kehtib sama ka Hugepagesi kohta. Kernel saab aga vahetada ainult terveid lehti, mitte üksikuid baite.

Oletame, et meil on selline programm:

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

Sel juhul peab kernel asendama (lugema) kõvakettalt/SSD-lt koguni 2 megabaiti teavet, et saaksite lugeda ühe baidi. Mis puutub tavalehtedesse, siis kõvakettalt/SSD-lt tuleb lugeda vaid 4096 baiti.

Seega, kui tohutu leht on tühistatud, on selle lugemine kiirem ainult siis, kui teil on vaja juurdepääsu kogu lehele. See tähendab, et kui proovite juhuslikult juurdepääsu erinevatele mäluosadele ja loete vaid paar kilobaiti, peaksite kasutama tavalisi lehti ja mitte muretsema millegi muu pärast.

Teisest küljest, kui teil on vaja järjestikku juurde pääseda suurele osale mälust, parandavad tohutud lehed teie jõudlust. Küll aga tuleb seda ise testida (mitte abstraktse tarkvaraga) ja vaadata, mis töötab kiiremini.

Jaotus mällu

Kui kirjutate C, teate, et saate kuhjast nõuda suvaliselt väikeseid (või peaaegu meelevaldselt suuri) mälumahtusid, kasutades malloc(). Oletame, et vajate 30 baiti mälu:

char* mymemory = malloc(30);

Programmeerijale võib tunduda, et te "taotate" operatsioonisüsteemilt 30 baiti mälu ja tagastate kursori mõnele virtuaalmällu. Aga tegelikult malloc () on lihtsalt C-funktsioon, mis kutsub funktsiooni seest brk ja sbrk opsüsteemi mälu taotlemiseks või vabastamiseks.

Kuid iga eraldamise jaoks üha rohkem mälu taotlemine on ebaefektiivne; suure tõenäosusega on mõni mälusegment juba vabastatud (free())ja saame seda uuesti kasutada. malloc() rakendab vabanenud mälu taaskasutamiseks üsna keerulisi algoritme.

Samas juhtub sinu jaoks kõik märkamatult, miks peaks see sind muretsema? Aga kuna väljakutse free() ei tähenda seda mälu tagastatakse kohe operatsioonisüsteemile.

On olemas selline asi nagu mälu killustatus. Äärmuslikel juhtudel on hunniku segmente, kus kasutatakse vaid mõnda baiti, samas kui kõik vahepealne on vabastatud (free()).

Pange tähele, et mälu killustatus on uskumatult keeruline teema ja isegi väiksematel programmimuudatustel võib olla märkimisväärne mõju. Enamikul juhtudel ei põhjusta programmid märkimisväärset mälu killustumist, kuid peaksite teadma, et kui mõnes kuhja piirkonnas on killustumise probleem, võivad suured lehed olukorda veelgi hullemaks muuta.

Suurte lehtede valikuline kasutamine

Pärast selle artikli lugemist olete kindlaks teinud, millised teie programmi osad saavad tohutute lehtede kasutamisest kasu ja millised mitte. Kas tohutud leheküljed peaksid olema üldse lubatud?

Õnneks saab kasutada madvise()lubada tohutut lehitsemist ainult nendes mälupiirkondades, kus see oleks kasulik.

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

Seejärel kasutage madvise()et öelda tuumale täpselt, kus tohutuid lehti 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 on lihtsalt nõuanne kernelile mälu haldamiseks. See ei tähenda, et kernel kasutab antud mälu jaoks automaatselt suuri lehti.

Vaadake dokumentatsiooni (manpage)madviseet rohkem teada saada mäluhalduse ja madvise(), sellel teemal on uskumatult järsk õppimiskõver. Nii et kui kavatsete selles väga hästi hakkama saada, valmistuge paar nädalat lugemiseks ja testimiseks, enne kui ootate positiivseid tulemusi.

Mida lugeda?

Kas teil on küsimus? Kirjuta kommentaaridesse!

Allikas: www.habr.com

Lisa kommentaar