Vantaghji è svantaghji di HugePages

Vantaghji è svantaghji di HugePages

Traduzzione di l'articulu preparatu per i studienti di u cursu "Amministratore Linux".

Prima, aghju parlatu di cumu pruvà è attivà Hugepages in Linux.
Questu articulu serà utile solu se avete veramente un locu per utilizà Hugepages. Aghju scontru assai persone chì sò ingannati da a prospettiva chì Hugepages migliurà magicamente a produtividade. Tuttavia, l'enorme paginazione hè un tema cumplessu è pò degradà u rendiment s'ellu hè utilizatu in modu incorrectu.

Parte 1: Verificate chì e pagine enormi sò attivate in Linux (uriginale ccà)

Problem:
Avete bisognu di verificà se HugePages hè attivatu in u vostru sistema.

suluzione:
Hè abbastanza simplice:

cat /sys/kernel/mm/transparent_hugepage/enabled

Averete qualcosa cum'è questu:

always [madvise] never

Vi vede una lista di l'opzioni dispunibili (sempre, pazza, mai), è l'opzione attualmente attiva serà chjusa in parentesi (per default pazza).

pazza significa chì transparent hugepages attivatu solu per e zone di memoria chì dumandanu esplicitamente l'usu di pagine enormi pazzia (2).

sempri significa chì transparent hugepages sempre attivatu per tutti i prucessi. Questu generalmente migliurà u rendiment, ma se avete un casu d'utilizazione induve parechji prucessi cunsumanu una piccula quantità di memoria, allora a carica di memoria generale pò aumentà drammaticamente.

mai significa chì transparent hugepages ùn serà micca inclusu ancu quandu hè dumandatu cù madvise. Per sapè di più, cuntattate ducumentazione kernels Linux.

Cumu cambià u valore predeterminatu

Opzione 1: Cambia direttamente sysfs (dopu à reboot u paràmetru tornerà à u so valore predeterminatu):

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

Opzione 2: Cambia u sistema predeterminatu recompilendu u kernel cù una cunfigurazione mudificata (sta opzione hè cunsigliatu solu s'è vo aduprate un kernel persunalizatu):

  • Per stabilisce sempre per automaticamente, utilizate:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Per stabilisce madvise cum'è predefinitu, utilizate:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Parte 2: Vantaghji è svantaghji di HugePages

Pruvaremu di spiegà in modu selettivu i vantaghji, i svantaghji è i pussibuli trappule di l'usu di Hugepages. Siccomu un articulu tecnologicu cumplessu è pedanticu serà prubabilmente difficiuli di capiscenu per e persone chì sò ingannati à pensà Hugepages hè una panacea, sacrificaraghju a precisione per a simplicità. Hè vale a pena tene in mente chì assai di i temi sò veramente cumplessi è dunque assai simplificati.

Per piacè nutate chì parlemu di sistemi 64-bit x86 chì funzionanu Linux, è chì sò solu supponendu chì u sistema sustene e pagine enormi trasparenti (perchè ùn hè micca un svantaghju chì e pagine enormi ùn sò micca sovrascritte), cum'è u casu in quasi ogni Linux mudernu. ambiente.

Aghju aghjustatu più descrizzione tecnica in i ligami sottu.

Memoria virtuale

Sè vo site un programatore C++, sapete chì l'uggetti in memoria anu indirizzi specifichi (valori di puntatore).

Tuttavia, questi indirizzi ùn anu micca necessariamente riflette l'indirizzi fisichi in memoria (indirizzi RAM). Rappresentanu indirizzi in memoria virtuale. U processatore hà un modulu MMU (unità di gestione di memoria) speciale chì aiuta à u kernel mappe a memoria virtuale à un locu fisicu.

Stu approcciu hà parechji vantaghji, ma i più impurtanti sò:

  • Prestazione (per diversi motivi);
  • L'isolamentu di u prugramma, vale à dì, nisun prugramma pò leghje da a memoria di un altru prugramma.

Chì sò e pagine?

A memoria virtuale hè divisa in pagine. Ogni pagina individuale punta à una memoria fisica specifica, pò indicà una zona in RAM, o ponu indicà un indirizzu assignatu à un dispositivu fisicu, cum'è una carta video.

A maiò parte di e pagine chì trattate o puntanu à RAM o sò scambiati, vale à dì chì sò almacenati in u vostru discu duru o SSD. U kernel gestisce u layout fisicu di ogni pagina. Se si accede à una pagina falsificata, u kernel ferma u filu chì prova à accede à a memoria, leghje a pagina da u discu duru / SSD in RAM, è poi cuntinueghja à eseguisce u filu.

Stu prucessu hè un flussu trasparente, vale à dì chì ùn hè micca necessariu leghje direttamente da u HDD / SSD. A dimensione di e pagine nurmale hè 4096 bytes. A dimensione di e pagine enormi hè 2 megabyte.

Buffer associativo di traduzione (TLB)

Quandu un prugramma accede à una pagina di memoria, u CPU deve sapè da quale pagina fisica leghje e dati (vale à dì, avè una mappa di l'indirizzu virtuale).

U kernel hà una struttura di dati (tavula di pagina) chì cuntene tutte l'infurmazioni nantu à e pagine chì sò aduprate. Utilizendu sta struttura di dati, pudete mapà un indirizzu virtuale à un indirizzu fisicu.

Tuttavia, a tabella di pagina hè abbastanza cumplessa è lenta, cusì ùn pudemu micca analizà a struttura di dati intera ogni volta chì un prucessu accede à a memoria.

Fortunatamente, u nostru processore hà un TLB chì cache a mappa trà l'indirizzi virtuale è fisicu. Questu significa chì, ancu s'ellu avemu bisognu di analizà a tabella di a pagina nantu à u primu tentativu di accessu, tutti l'accessi successivi à a pagina ponu esse trattati in u TLB, chì permettenu un'operazione rapida.

Perchè hè implementatu cum'è un dispositivu fisicu (chì face u rapidu in u primu locu), a so capacità hè limitata. Allora se vulete accede à più pagine, u TLB ùn serà micca capaci di almacenà mappings per tutti, facendu chì u vostru prugramma scorri assai più lento.

Hugepages vene in salvezza

Allora chì pudemu fà per evità TLB overflow? (Assumimu chì u prugramma hà sempre bisognu di a stessa quantità di memoria).

Hè quì chì entra in Hugepages. Invece di 4096 byte chì necessitanu una sola entrata TLB, una entrata TLB pò avà indicà un enorme 2 megabyte. Assumimu chì u TLB hà 512 entrate, quì senza Hugepages pudemu currisponde à:

4096 b⋅512=2 MB

Allora cumu pudemu paragunà cun elli:

2 MB⋅512=1 GB

Hè per quessa Hugepages hè stupente. Puderanu migliurà a produtividade senza assai sforzu. Ma ci sò caveats significativu quì.

Enorme spoofing di pagine

U kernel monitoreghja automaticamente quante volte ogni pagina di memoria hè aduprata. Se ùn ci hè micca abbastanza memoria fisica (RAM), u kernel moverà e pagine menu impurtanti (usate menu freti) à u discu duru per liberà qualchì RAM per e pagine più impurtanti.
In principiu, u listessu vale per Hugepages. Tuttavia, u kernel pò scambià solu pagine intere, micca byte individuali.

Diciamu chì avemu un prugramma cum'è questu:

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

In questu casu, u kernel hà bisognu di rimpiazzà (leghje) quant'è 2 megabytes d'infurmazioni da u discu duru / SSD solu per voi per leghje un byte. In quantu à e pagine regulare, solu 4096 bytes deve esse lettu da u discu duru / SSD.

Dunque, se l'enorme pagina hè annullata, hè solu più veloce per leghje s'ellu avete bisognu di accede à tutta a pagina. Questu significa chì sè vo circate d'accede in modu aleatoriu à e diverse parti di a memoria è site solu leghje un paru di kilobyte, duvete aduprà pagine regulare è ùn preoccupate micca di nunda.

Per d 'altra banda, sè avete bisognu di accede à una grande parte di memoria sequenziale, e pagine enormi migliurà u vostru rendimentu. Tuttavia, avete bisognu di pruvà stessu (micca cù software astrattu) è vede ciò chì travaglia più veloce.

Allocazione in memoria

Se scrivite C, sapete chì pudete dumandà quantità di memoria arbitrariamente chjuca (o quasi arbitrariamente grande) da u munzeddu usendu malloc(). Diciamu chì avete bisognu di 30 bytes di memoria:

char* mymemory = malloc(30);

À un programatore, pò pare chì site "dumandu" 30 bytes di memoria da u sistema operatore è rinvià un punteru à qualchì memoria virtuale. Ma in realtà malloc () hè solu una funzione C chì chjama da a funzione brk è sbrk per dumandà o liberà memoria da u sistema operatore.

In ogni casu, dumandà più è più memoria per ogni allocazione hè inefficient; hè più prubabile chì qualchì segmentu di memoria hè digià statu liberatu (free()), è pudemu riutilizà. malloc() implementa algoritmi abbastanza cumplessi per riutilizà a memoria liberata.

À u listessu tempu, tuttu passa inosservatu per voi, allora perchè vi preoccupa? Ma perchè a sfida free() ùn significa micca questu A memoria hè necessariamente tornata immediatamente à u sistema operatore.

Ci hè una cosa cum'è a frammentazione di memoria. In i casi estremi, ci sò segmenti di monti induve sò usati solu uni pochi byte, mentre chì tuttu in trà hè statu liberatu. (free()).

Per piacè nutate chì a frammentazione di memoria hè un tema incredibbilmente cumplessu, è ancu i cambiamenti minori à un prugramma ponu avè un impattu significativu. In a maiò parte di i casi, i prugrammi ùn pruvucanu micca una frammentazione significativa di a memoria, ma duvete esse cuscenti chì s'ellu ci hè un prublema cù a frammentazione in una certa zona di u munzeddu, e pagine enormi ponu peghju a situazione.

Usu selettivu di pagine enormi

Dopu avè lettu l'articulu, avete determinatu quali parti di u vostru prugramma ponu benefiziu da l'usu di pagine enormi è quale ùn pò micca. Allora deve esse attivate e pagine enormi?

Per furtuna pudete aduprà madvise()per attivà l'enorme paginazione solu per quelli spazii di memoria induve saria utile.

Prima, verificate chì hugepages funziona in modu madvise () usendu instructions à u principiu di l'articulu.

Allora, aduprà madvise()per dì à u kernel esattamente induve aduprà 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)

Nota chì stu metudu hè solu cunsiglii à u kernel nantu à cumu gestisce a memoria. Questu ùn significa micca chì u kernel utilizerà automaticamente pagine enormi per una memoria data.

Vede a documentazione (manpage) cunsigliuper sapè più nantu à a gestione di a memoria è madvise(), stu tema hà una curva di apprendimentu incredibilmente ripida. Allora s'è vo vulete ottene veramente bè, preparate per leghje è pruvà per uni pochi di settimane prima di aspittà un risultatu pusitivu.

Cosa à leghje?

Avete una quistione? Scrivite in i cumenti!

Source: www.habr.com

Add a comment