Avantazhet dhe disavantazhet e HugePages

Avantazhet dhe disavantazhet e HugePages

Përkthimi i artikullit të përgatitur për studentët e kursit "Administrator Linux".

Më parë, fola se si të kontrolloj dhe aktivizoj përdorimin e Hugepages në Linux.
Ky artikull do të jetë i dobishëm vetëm nëse keni një rast përdorimi për Hugepages. Kam hasur shumë njerëz që mashtrohen nga premtimi se Hugepages do të rrisë magjikisht performancën. Megjithatë, hugepages është një temë komplekse dhe, nëse përdoret gabimisht, mund të ulë performancën.

Pjesa 1: Kontrollimi nëse hugepages janë aktivizuar në Linux (origjinali) këtu)

problem:
Duhet të kontrolloni nëse HugePages është aktivizuar në sistemin tuaj.

zgjidhje:
Është mjaft e thjeshtë:

cat /sys/kernel/mm/transparent_hugepage/enabled

Do të merrni diçka si kjo:

always [madvise] never

Do të shihni një listë të opsioneve të disponueshme (gjithmonë, i çmendur, kurrë), ndërsa opsioni aktualisht aktiv do të mbyllet në kllapa (sipas parazgjedhjes i çmendur).

i çmendur do të thotë se transparent hugepages aktivizohet vetëm për zonat e memories që kërkojnë në mënyrë të qartë hugepages duke përdorur madvise(2).

gjithmonë do të thotë se transparent hugepages Aktivizuar në çdo kohë dhe për të gjitha proceset. Kjo zakonisht përmirëson performancën, por nëse keni një rast përdorimi ku shumë procese konsumojnë një sasi të vogël memorieje, ngarkesa e përgjithshme e memories mund të rritet ndjeshëm.

asnjehere do të thotë se transparent hugepages nuk do të përfshihet edhe kur kërkohet duke përdorur madvise. Për më shumë informacion, ju lutemi referojuni dokumentacionin Bërthamat e Linux-it.

Si të ndryshoni vlerën e parazgjedhur

Opsioni 1: Ndrysho drejtpërdrejt sysfs (pas rinisjes, parametri do të kthehet në vlerën e tij të paracaktuar):

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

Opsioni 2Ndryshoni parazgjedhjen e sistemit duke rikompiluar kernelin me konfigurimin e ndryshuar (ky opsion rekomandohet vetëm nëse po përdorni një kernel të personalizuar):

  • Për ta vendosur gjithmonë si parazgjedhje, përdorni:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Për të vendosur madvise si parazgjedhje, përdorni:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Pjesa 2: Avantazhet dhe Disavantazhet e HugePages

Do të përpiqemi të shpjegojmë në mënyrë selektive avantazhet, disavantazhet dhe rreziqet e mundshme të përdorimit të Hugepages. Meqenëse një artikull teknologjikisht kompleks dhe pedant ka të ngjarë të jetë i vështirë për t’u kuptuar nga ata që mashtrohen duke menduar se Hugepages është një ilaç për të gjitha problemet, do të sakrifikoj saktësinë për hir të thjeshtësisë. Ia vlen të mbahet mend se shumë tema janë vërtet komplekse dhe për këtë arsye shumë të thjeshtuara.

Vini re se po flasim për sisteme 64-bit x86 që përdorin Linux, dhe se unë thjesht po supozoj se sistemi mbështet hugepages transparente (meqenëse nuk është një disavantazh që hugepages nuk zëvendësohen), siç është rasti në pothuajse çdo mjedis modern Linux.

Do të bashkëngjit më shumë përshkrime teknike në lidhjet më poshtë.

Kujtesa virtuale

Nëse jeni programues në C++, e dini që objektet në memorie kanë adresa specifike (vlera treguesi).

Megjithatë, këto adresa nuk pasqyrojnë domosdoshmërisht adresat e memories fizike (adresat RAM). Ato përfaqësojnë adresat e memories virtuale. Procesori ka një modul të veçantë, MMU (njësia e menaxhimit të memories), i cili ndihmon bërthamën të hartëzojë memorien virtuale në vendndodhje fizike.

Kjo qasje ka shumë përparësi, por më të rëndësishmet janë:

  • Produktiviteti (për arsye të ndryshme);
  • Izolimi i programit, që do të thotë se asnjë program nuk mund të lexojë nga memoria e një programi tjetër.

Çfarë janë faqet?

Kujtesa virtuale është e ndarë në faqe. Çdo faqe individuale tregon një vendndodhje specifike të memories fizike, e cila mund të jetë ose një vendndodhje në RAM ose një adresë e caktuar për një pajisje fizike, siç është një kartë grafike.

Shumica e faqeve me të cilat bashkëveproni ose tregojnë RAM ose janë të ndërruara, që do të thotë se ato ruhen në një hard disk ose SSD. Bërthama menaxhon vendndodhjen fizike të secilës faqe. Nëse aksesohet një faqe e ndërruar, bërthama ndalon përpjekjen e thread-it për të aksesuar memorien, e lexon faqen nga hard disku/SSD në RAM dhe më pas vazhdon ekzekutimin e thread-it.

Ky proces është transparent ndaj fijeve, që do të thotë se nuk lexon domosdoshmërisht direkt nga hard disku/SSD-ja. Faqet normale janë 4096 bajt në madhësi. Faqet e mëdha janë 2 megabajt në madhësi.

Translation Lookaside Buffer (TLB)

Kur një program hyn në një faqe memorieje, CPU-ja duhet të dijë nga cila faqe fizike t'i lexojë të dhënat (domethënë, duhet të ketë një hartë adresash virtuale).

Bërthama ka një strukturë të dhënash (tabela e faqeve) që përmban të gjithë informacionin në lidhje me faqet në përdorim. Kjo strukturë të dhënash lejon lidhjen e një adrese virtuale me një adresë fizike.

Megjithatë, tabela e faqeve është mjaft komplekse dhe e ngadaltë, kështu që thjesht nuk mund ta analizojmë të gjithë strukturën e të dhënave sa herë që një proces i qaset memories.

Për fat të mirë, procesori ynë ka një TLB, i cili ruan në memorje të përkohshme përputhjen midis adresave virtuale dhe fizike. Kjo do të thotë që, megjithëse duhet të analizojmë tabelën e faqeve për përpjekjen e parë të aksesit, të gjitha akseset pasuese në faqe mund të përpunohen në TLB, duke siguruar një funksionim të shpejtë.

Meqenëse është implementuar si një pajisje fizike (gjë që e bën të shpejtë që në fillim), kapaciteti i tij është i kufizuar. Prandaj, nëse doni të keni akses në më shumë faqe, TLB nuk do të jetë në gjendje të ruajë hartat për të gjitha ato, duke bërë që programi juaj të funksionojë shumë më ngadalë.

Hugepages vjen në shpëtim

Pra, çfarë mund të bëjmë për të shmangur mbingarkesën e TLB-së? (Supozojmë se programi ende ka nevojë për të njëjtën sasi memorieje.)

Këtu hyn në lojë Hugepages. Në vend të 4096 bajteve që kërkojnë vetëm një hyrje TLB, një hyrje e vetme TLB tani mund të tregojë një total prej 2 megabajtësh. Duke supozuar një TLB me 512 hyrje, pa Hugepages, ne mund të hartëzojmë:

4096 b⋅512=2 MB

Atëherë si mund t’i krahasojmë ato me:

2 MB⋅512=1 GB

Kjo është arsyeja pse Hugepages janë kaq të mirë. Ato mund të rrisin produktivitetin pa shumë përpjekje. Por ka disa paralajmërime të rëndësishme.

Zëvendësimi i Hugepages

Bërthama monitoron automatikisht se sa shpesh përdoret secila faqe e memories. Nëse memoria fizike (RAM) është e pamjaftueshme, bërthama do të zhvendosë faqet më pak të rëndësishme (më pak të përdorura) në hard disk për të liruar pak RAM për faqet më të rëndësishme.
Në parim, e njëjta gjë vlen edhe për Hugepages. Megjithatë, kerneli mund të shkëmbejë vetëm faqe të tëra, jo bajt individualë.

Le të supozojmë se kemi një program si ky:

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

Në këtë rast, kerneli do të duhej të shkëmbente (lexonte) plot 2 megabajt informacion nga hard disku/SSD vetëm që ju të lexoni një bajt. Për faqet e rregullta, vetëm 4096 bajt duhen lexuar nga hard disku/SSD.

Prandaj, nëse hugepage ndërrohet, leximi i tij është më i shpejtë vetëm nëse ju duhet të qaseni në të gjithë faqen. Kjo do të thotë që nëse po qaseni rastësisht në pjesë të ndryshme të memories dhe lexoni vetëm disa kilobajt, duhet të përdorni faqe të rregullta dhe të mos shqetësoheni për asgjë tjetër.

Nga ana tjetër, nëse keni nevojë të qaseni një pjesë të madhe të memories në mënyrë sekuenciale, hugepages do të përmirësojë performancën tuaj. Megjithatë, do t'ju duhet ta testoni vetë këtë (jo me softuer abstrakt) dhe të shihni se cili funksionon më shpejt.

Ndarja e kujtesës

Nëse shkruani C, e dini që mund të kërkoni sasi arbitrarisht të vogla (ose pothuajse arbitrarisht të mëdha) të memories nga grumbulli duke përdorur malloc()Le të themi se ju nevojiten 30 bajt memorie:

char* mymemory = malloc(30);

Për një programues, mund të duket sikur po "kërkon" 30 bajt memorie nga sistemi operativ dhe po kthen një tregues në një memorie virtuale. Por në realitet, malloc () — është vetëm një funksion C që thërret funksione nga brenda brk dhe sbrk për të kërkuar ose liruar memorie nga sistemi operativ.

Megjithatë, kërkesa për gjithnjë e më shumë memorie për secilën ndarje është joefikase; ka shumë të ngjarë që një segment memorieje të jetë liruar tashmë. (free()), dhe ne mund ta ripërdorim atë. malloc() Zbaton algoritme mjaft komplekse për ripërdorimin e memories së liruar.

E megjithatë, për ty, gjithçka ndodh pa u vënë re, kështu që pse duhet të të shqetësojë? Sepse sfida free() nuk do të thotë që memoria kthehet gjithmonë menjëherë në sistemin operativ.

Ekziston një koncept i quajtur fragmentim i memories. Në raste ekstreme, ka segmente të heap-it ku përdoren vetëm disa bajt, ndërsa çdo gjë midis tyre është liruar. (free()).

Ju lutemi vini re se fragmentimi i kujtesës është një temë tepër komplekse, dhe madje edhe ndryshimet e vogla në një program mund ta ndikojnë ndjeshëm atë. Në shumicën e rasteve, programet nuk shkaktojnë fragmentim të konsiderueshëm të kujtesës, por duhet të jeni të vetëdijshëm se nëse fragmentimi është një problem në një zonë specifike të heap-it, hugepages vetëm sa mund ta përkeqësojnë situatën.

Përdorim selektiv i faqeve të mëdha

Pasi ta keni lexuar këtë artikull, keni përcaktuar se cilat pjesë të programit tuaj mund të përfitojnë nga hugepages dhe cilat jo. Pra, a duhet ta aktivizoni fare hugepages?

Për fat të mirë, mund të përdorni madvise()për të aktivizuar hugepageging vetëm për ato zona të memories ku do të jetë i dobishëm.

Së pari, kontrolloni që hugepages po funksionon në modalitetin madvise() duke përdorur udhëzime në fillim të artikullit.

Pastaj, përdorni madvise()për t'i treguar kernelit saktësisht se ku të përdorë 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)

Ju lutem vini re se kjo metodë është thjesht një rekomandim për menaxhimin e kujtesës për kernelin. Kjo nuk do të thotë që kerneli do të përdorë automatikisht hugepages për kujtesën e dhënë.

Ju lutemi referojuni dokumentacionit (faqe manuale) madvisepër të mësuar më shumë rreth menaxhimit të kujtesës dhe madvise()Kjo temë ka një kurbë mësimi tepër të vështirë. Pra, nëse doni ta kuptoni vërtet, përgatituni ta lexoni dhe ta testoni për disa javë përpara se të prisni ndonjë rezultat pozitiv.

Çfarë të lexosh?

Keni ndonjë pyetje? Lini një koment!

Burimi: www.habr.com

Shto një koment