Avantaĝoj kaj Malavantaĝoj de HugePages

Avantaĝoj kaj Malavantaĝoj de HugePages

Traduko de la artikolo preparita por kursanoj "Linuksa Administranto".

Antaŭe, mi parolis pri kiel testi kaj ebligi la uzon de Hugepages en Linukso.
Ĉi tiu artikolo nur estos utila se vi efektive havas lokon por uzi Hugepages. Mi renkontis multajn homojn, kiuj estas trompitaj de la perspektivo, ke Hugepages magie plibonigos produktivecon. Tamen, grandega pagado estas kompleksa temo kaj povas malbonigi efikecon se uzata malĝuste.

Parto 1: Kontrolante ke grandegaj paĝoj estas ebligitaj en Linukso (originala tie)

Problemo:
Vi devas kontroli ĉu HugePages estas ebligita en via sistemo.

solvo:
Ĝi estas sufiĉe simpla:

cat /sys/kernel/mm/transparent_hugepage/enabled

Vi ricevos ion tian:

always [madvise] never

Vi vidos liston de disponeblaj opcioj (ĉiam, freneze, neniam), kaj la aktuale aktiva opcio estos enfermita inter krampoj (defaŭlte freneza).

freneza signifas tion transparent hugepages ebligita nur por memorareoj kiuj eksplicite petas grandegajn paĝojn uzante freneza (2).

ĉiam signifas tion transparent hugepages ĉiam ebligita por ĉiuj procezoj. Ĉi tio kutime plibonigas rendimenton, sed se vi havas uzkazon kie multaj procezoj konsumas malgrandan kvanton da memoro, tiam la ĝenerala memorŝarĝo povas pliiĝi draste.

neniam signifas tion transparent hugepages ne estos inkluzivita eĉ kiam oni petas per madvise. Por ekscii pli, kontaktu dokumentado Linuksaj kernoj.

Kiel ŝanĝi la defaŭltan valoron

Eblo 1: Rekte ŝanĝi sysfs (post rekomenco la parametro revenos al sia defaŭlta valoro):

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

Eblo 2: Ŝanĝu la sisteman defaŭltan rekompilante la kernon kun modifita agordo (ĉi tiu opcio estas rekomendita nur se vi uzas kutiman kernon):

  • Por agordi ĉiam defaŭlte, uzu:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Por agordi madvise kiel defaŭltan, uzu:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Parto 2: Avantaĝoj kaj Malavantaĝoj de HugePages

Ni provos selekteme klarigi la avantaĝojn, malavantaĝojn kaj eblajn kaptilojn de uzado de Hugepages. Ĉar teknologie kompleksa kaj pedanta artikolo verŝajne estos malfacile komprenebla por homoj, kiuj trompas pensadon, ke Hugepages estas panaceo, mi oferos precizecon por simpleco. Nur indas konsideri, ke multaj temoj estas vere kompleksaj kaj do tre simpligitaj.

Bonvolu noti, ke ni parolas pri 64-bitaj x86-sistemoj, kiuj funkcias Linukso, kaj ke mi simple supozas, ke la sistemo subtenas travideblajn grandegajn paĝojn (ĉar ne estas malavantaĝo, ke grandegaj paĝoj ne estas anstataŭitaj), kiel estas la kazo en preskaŭ ajna moderna Linukso. medio.

Mi aldonos pli da teknika priskribo en la subaj ligiloj.

Virtuala Memoro

Se vi estas C++-programisto, vi scias, ke objektoj en memoro havas specifajn adresojn (montrilo-valoroj).

Tamen, ĉi tiuj adresoj ne nepre reflektas fizikajn adresojn en memoro (RAM-adresoj). Ili reprezentas adresojn en virtuala memoro. La procesoro havas specialan modulon MMU (memormastruma unuo) kiu helpas al la kerno mapi virtualan memoron al fizika loko.

Ĉi tiu aliro havas multajn avantaĝojn, sed la plej gravaj estas:

  • Rendimento (pro diversaj kialoj);
  • Programa izolado, tio estas, neniu programo povas legi el la memoro de alia programo.

Kio estas paĝoj?

Virtuala memoro estas dividita en paĝojn. Ĉiu individua paĝo montras al specifa fizika memoro, ĝi povas montri al areo en RAM, aŭ ĝi povas montri al adreso asignita al fizika aparato, kiel vidkarto.

La plej multaj el la paĝoj, kiujn vi traktas, montras al RAM aŭ estas interŝanĝitaj, tio signifas, ke ili estas konservitaj sur via malmola disko aŭ SSD. La kerno administras la fizikan aranĝon de ĉiu paĝo. Se parodiita paĝo estas alirita, la kerno ĉesigas la fadenon kiu provas aliri la memoron, legas la paĝon de la malmola disko/SSD en RAM, kaj tiam daŭrigas ekzekuti la fadenon.

Ĉi tiu procezo estas travidebla, kio signifas, ke ĝi ne nepre legas rekte de la HDD/SSD. La grandeco de normalaj paĝoj estas 4096 bajtoj. Grandega paĝa grandeco estas 2 megabajtoj.

Traduk-asocieca bufro (TLB)

Kiam programo aliras paĝon de memoro, la CPU devas scii de kiu fizika paĝo legi datumojn (t.e. havi virtualan adresmapon).

La kerno havas datumstrukturon (paĝtabelo) kiu enhavas ĉiujn informojn pri la paĝoj uzataj. Uzante ĉi tiun datuman strukturon, vi povas mapi virtualan adreson al fizika adreso.

Tamen, la paĝa tabelo estas sufiĉe kompleksa kaj malrapida, do ni simple ne povas analizi la tutan datumstrukturon ĉiufoje kiam procezo aliras memoron.

Feliĉe, nia procesoro havas TLB, kiu konservas la mapadon inter virtualaj kaj fizikaj adresoj. Ĉi tio signifas, ke kvankam ni devas analizi la paĝan tabelon ĉe la unua aliro provo, ĉiuj postaj aliroj al la paĝo povas esti pritraktitaj en la TLB, ebligante rapidan operacion.

Ĉar ĝi estas efektivigita kiel fizika aparato (kiu faras ĝin rapida en la unua loko), ĝia kapablo estas limigita. Do se vi volas aliri pli da paĝoj, la TLB ne povos stoki mapadojn por ĉiuj ili, kaŭzante vian programon multe pli malrapide.

Hugepages venas al la savo

Do kion ni povas fari por eviti TLB-superfluon? (Ni supozas, ke la programo ankoraŭ bezonas la saman kvanton da memoro).

Jen kie Hugepages eniras. Anstataŭ 4096 bajtoj postulantaj nur unu TLB-eniron, unu TLB-eniro nun povas indiki enormajn 2 megabajtojn. Ni supozu, ke la TLB havas 512 enskribojn, ĉi tie sen Hugepages ni povas egali:

4096 b⋅512=2 MB

Tiam kiel ni povas kompari kun ili:

2 MB⋅512=1 GB

Jen kial Hugepages estas mirinda. Ili povas plibonigi produktivecon sen multe da peno. Sed estas gravaj avertoj ĉi tie.

Hugepages parodiado

La kerno aŭtomate kontrolas kiom ofte ĉiu memorpaĝo estas uzata. Se ne estas sufiĉe da fizika memoro (RAM), la kerno movos malpli gravajn (malpli ofte uzatajn) paĝojn al la malmola disko por liberigi iom da RAM por pli gravaj paĝoj.
Principe, la sama validas por Hugepages. Tamen, la kerno povas nur interŝanĝi tutajn paĝojn, ne individuajn bajtojn.

Ni diru, ke ni havas programon tia:

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

En ĉi tiu kazo, la kerno devos anstataŭigi (legi) eĉ 2 megabajtojn da informoj de la malmola disko/SSD nur por ke vi legu unu bajton. Kiel por regulaj paĝoj, nur 4096 bajtoj devas esti legitaj de la malmola disko/SSD.

Sekve, se grandega paĝo estas anstataŭita, ĝi estas nur pli rapide legi se vi bezonas aliri la tutan paĝon. Ĉi tio signifas, ke se vi provas hazarde aliri malsamajn partojn de memoro kaj nur legas kelkajn kilobajtojn, vi devus uzi regulajn paĝojn kaj ne zorgi pri io alia.

Aliflanke, se vi bezonas aliri grandan parton de memoro sinsekve, grandegaj paĝoj plibonigos vian rendimenton. Tamen, vi devas provi ĝin mem (ne per abstrakta programaro) kaj vidi kio funkcias pli rapide.

Asigno en memoro

Se vi skribas C, vi scias, ke vi povas peti arbitre malgrandajn (aŭ preskaŭ arbitre grandajn) kvantojn da memoro el la amaso uzante malloc(). Ni diru, ke vi bezonas 30 bajtojn da memoro:

char* mymemory = malloc(30);

Al programisto, povas ŝajni, ke vi "petas" 30 bajtojn da memoro de la operaciumo kaj resendas montrilon al iu virtuala memoro. Sed efektive malloc () estas nur C-funkcio kiu vokas de ene de la funkcio brk kaj sbrk peti aŭ liberigi memoron de la operaciumo.

Tamen, peti pli kaj pli da memoro por ĉiu asigno estas malefika; plej verŝajne iu memorsegmento jam estis liberigita (free()), kaj ni povas reuzi ĝin. malloc() efektivigas sufiĉe kompleksajn algoritmojn por reuzi liberigitan memoron.

Samtempe ĉio okazas nerimarkite por vi, do kial ĝi zorgu vin? Sed ĉar la defio free() ne signifas tion memoro estas nepre resendita tuj al la operaciumo.

Ekzistas tia afero kiel memorfragmentiĝo. En ekstremaj kazoj, ekzistas amasaj segmentoj kie nur kelkaj bajtoj estas uzitaj, dum ĉio intere estis liberigita. (free()).

Bonvolu noti, ke memorfragmentado estas nekredeble kompleksa temo, kaj eĉ etaj ŝanĝoj al programo povas havi gravan efikon. Plejofte, programoj ne kaŭzos gravan fragmentiĝon de memoro, sed vi devas konscii, ke se estas problemo pri fragmentiĝo en iu areo de la amaso, grandegaj paĝoj povas plimalbonigi la situacion.

Selektema uzo de grandegaj paĝoj

Post legi ĉi tiun artikolon, vi determinis, kiuj partoj de via programo povas profiti de uzado de grandegaj paĝoj kaj kiuj ne povas. Do ĉu hugepages entute estu ebligitaj?

Feliĉe vi povas uzi madvise()por ebligi grandegan paĝon nur por tiuj memorareoj kie ĝi estus utila.

Unue, kontrolu, ke hugepages funkcias en madvise() reĝimo uzante instrukcioj komence de la artikolo.

Poste, uzu madvise()por diri al la kerno precize kie uzi grandegajn paĝojn.

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

Notu, ke ĉi tiu metodo estas simple konsilo al la kerno pri kiel administri memoron. Ĉi tio ne signifas, ke la kerno aŭtomate uzos grandegajn paĝojn por difinita memoro.

Vidu al dokumentado (manpage)frenezalerni pli pri memoradministrado kaj madvise(), ĉi tiu temo havas nekredeble krutan lernkurbon. Do se vi intencas tre bone pri ĝi, preparu legi kaj testi dum kelkaj semajnoj antaŭ ol vi atendas pozitivajn rezultojn.

Kion legi?

Ĉu vi havas demandon? Skribu en la komentoj!

fonto: www.habr.com

Aldoni komenton