Korábban beszéltem arról, hogyan tesztelhetem és engedélyezhetem a Hugepages-t Linuxon.
Ez a cikk csak akkor lesz hasznos, ha valóban van helye a Hugepages használatára. Sok emberrel találkoztam, akiket megtéveszt az a kilátás, hogy a Hugepages varázslatosan javítani fogja a termelékenységet. A hatalmas lapozás azonban összetett téma, és ronthatja a teljesítményt, ha helytelenül használják.
1. rész: Annak ellenőrzése, hogy a hatalmas oldalak engedélyezve vannak-e Linuxon (eredeti itt)
probléma:
Ellenőriznie kell, hogy a HugePages engedélyezve van-e a rendszeren.
megoldás:
Ez elég egyszerű:
cat /sys/kernel/mm/transparent_hugepage/enabled
Valami ilyesmit fog kapni:
always [madvise] never
Megjelenik az elérhető opciók listája (mindig, madvise, soha), és a jelenleg aktív opció zárójelben lesz (alapértelmezés szerint őrült).
őrült azt jelenti, hogy transparent hugepages csak azokon a memóriaterületeken engedélyezett, amelyek kifejezetten nagy oldalakat igényelnek madvise (2).
mindig azt jelenti, hogy transparent hugepages mindig engedélyezve van minden folyamathoz. Ez általában javítja a teljesítményt, de ha olyan használati esettel rendelkezik, amikor sok folyamat kis mennyiségű memóriát fogyaszt, akkor a teljes memóriaterhelés drámaian megnőhet.
soha azt jelenti, hogy transparent hugepages akkor sem kerül bele, ha a madvise használatával kérik. További információért vegye fel a kapcsolatot dokumentáció Linux kernelek.
Az alapértelmezett érték megváltoztatása
Az 1 opció: Közvetlenül változás sysfs (újraindítás után a paraméter visszaáll az alapértelmezett értékre):
echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled
Az 2 opció: Módosítsa a rendszer alapértelmezett értékét a kernel módosított konfigurációval történő újrafordításával (ez a lehetőség csak akkor ajánlott, ha egyéni kernelt használ):
A mindig alapértelmezés szerinti beállításhoz használja:
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
# Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
A madvise alapértelmezett beállításához használja:
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
# Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
2. rész: A HugePages előnyei és hátrányai
Igyekszünk szelektíven elmagyarázni a Hugepages használatának előnyeit, hátrányait és lehetséges buktatóit. Mivel egy technológiailag összetett és pedáns cikket valószínűleg nehéz lesz megérteni azok számára, akik el vannak tévedve azzal, hogy a Hugepages csodaszer, ezért feláldozom a pontosságot az egyszerűségért. Csak azt érdemes szem előtt tartani, hogy sok téma nagyon összetett, ezért nagyon leegyszerűsödik.
Kérjük, vegye figyelembe, hogy Linuxot futtató 64 bites x86-os rendszerekről beszélünk, és egyszerűen abból indulok ki, hogy a rendszer támogatja az átlátszó hatalmas oldalakat (hiszen nem hátrány, hogy a hatalmas oldalakat nem írják felül), mint szinte minden modern Linuxban. környezet.
További technikai leírást mellékelek az alábbi linkeken.
Virtuális memória
Ha Ön C++ programozó, akkor tudja, hogy a memóriában lévő objektumok meghatározott címekkel (mutatóértékekkel) rendelkeznek.
Ezek a címek azonban nem feltétlenül tükrözik a memóriában lévő fizikai címeket (RAM-címeket). Címeket képviselnek a virtuális memóriában. A processzor egy speciális MMU (memóriakezelő egység) modullal rendelkezik, amely segít a kernelnek leképezni a virtuális memóriát egy fizikai helyre.
Ennek a megközelítésnek számos előnye van, de a legfontosabbak a következők:
Teljesítmény (különböző okokból);
Programizoláció, vagyis egyetlen program sem tud olvasni egy másik program memóriájából.
Mik azok az oldalak?
A virtuális memória lapokra van felosztva. Minden egyes oldal egy adott fizikai memóriára mutat, mutathat egy területet a RAM-ban, vagy mutathat egy fizikai eszközhöz, például videokártyához rendelt címre.
Az Ön által kezelt oldalak többsége vagy a RAM-ra mutat, vagy fel van cserélve, vagyis a merevlemezen vagy az SSD-n vannak tárolva. A kernel kezeli az egyes oldalak fizikai elrendezését. Hamisított oldal elérése esetén a kernel leállítja a memóriát elérni kívánó szálat, beolvassa az oldalt a merevlemezről/SSD-ről a RAM-ba, majd folytatja a szál végrehajtását.
Ez a folyamat stream-átlátszó, vagyis nem feltétlenül olvas közvetlenül a HDD/SSD-ről. A normál oldalak mérete 4096 bájt. A hatalmas oldalak mérete 2 megabájt.
Fordítás-asszociatív puffer (TLB)
Amikor egy program hozzáfér egy memóriaoldalhoz, a CPU-nak tudnia kell, hogy melyik fizikai oldalról olvassa ki az adatokat (vagyis rendelkeznie kell egy virtuális címtérképpel).
A kernelnek van egy adatstruktúrája (oldaltáblázata), amely a használt oldalakkal kapcsolatos összes információt tartalmazza. Ezzel az adatszerkezettel leképezhet egy virtuális címet egy fizikai címre.
Az oldaltábla azonban meglehetősen összetett és lassú, így egyszerűen nem tudjuk elemezni a teljes adatstruktúrát minden alkalommal, amikor egy folyamat hozzáfér a memóriához.
Szerencsére a processzorunk rendelkezik egy TLB-vel, amely gyorsítótárazza a virtuális és fizikai címek leképezését. Ez azt jelenti, hogy bár az oldaltáblázatot az első hozzáférési kísérletnél elemezni kell, az oldal minden további elérése kezelhető a TLB-ben, ami lehetővé teszi a gyors működést.
Mivel fizikai eszközként valósítják meg (ami elsősorban gyorsítja), kapacitása korlátozott. Tehát ha több oldalhoz szeretne hozzáférni, a TLB nem tudja mindegyikhez leképezést tárolni, ami miatt a program sokkal lassabban fut.
Hugepages jön a megmentésre
Mit tehetünk tehát a TLB túlcsordulás elkerülése érdekében? (Feltételezzük, hogy a programnak még mindig ugyanannyi memóriára van szüksége).
Itt jön be a Hugepages. Ahelyett, hogy 4096 bájt csak egy TLB-bejegyzést igényelne, egy TLB-bejegyzés immár hatalmas 2 megabájtra mutathat. Tegyük fel, hogy a TLB-nek 512 bejegyzése van, itt a Hugepages nélkül párosíthatunk:
4096 b⋅512=2 MB
Akkor hogyan hasonlítsuk össze őket:
2 MB⋅512=1 GB
Ezért fantasztikus a Hugepages. Nagy erőfeszítés nélkül javíthatják a termelékenységet. De vannak itt jelentős figyelmeztetések.
Hatalmas oldalak hamisítása
A kernel automatikusan figyeli, hogy az egyes memórialapokat milyen gyakran használják. Ha nincs elég fizikai memória (RAM), a kernel áthelyezi a kevésbé fontos (ritkábban használt) oldalakat a merevlemezre, hogy felszabadítson egy kis RAM-ot a fontosabb oldalak számára.
Elvileg ugyanez vonatkozik a Hugepages-re is. A kernel azonban csak teljes oldalakat tud felcserélni, egyes bájtokat nem.
Tegyük fel, hogy van egy ilyen programunk:
char* mymemory = malloc(2*1024*1024); // Возьмем это за одну Hugepage!
// Заполним mymemory какими-либо данными
// Сделаем много других вещей,
// которые приведут к подмене страницы mymemory
// ...
// Запросим доступ только к первому байту
putchar(mymemory[0]);
Ebben az esetben a kernelnek 2 megabájtnyi információt kell kicserélnie (beolvasnia) a merevlemezről/SSD-ről, csak hogy Ön egy bájtot beolvashasson. Ami a normál oldalakat illeti, csak 4096 bájtot kell beolvasni a merevlemezről/SSD-ről.
Ezért, ha a hatalmas oldalt felülírják, akkor csak akkor gyorsabb az olvasás, ha el kell érnie a teljes oldalt. Ez azt jelenti, hogy ha véletlenszerűen próbál hozzáférni a memória különböző részeihez, és csak néhány kilobájtot olvas, használjon szokásos oldalakat, és ne aggódjon semmi más miatt.
Másrészt, ha a memória nagy részét szekvenciálisan kell elérnie, a hatalmas oldalak javítják a teljesítményt. Azonban magának kell tesztelnie (nem absztrakt szoftverrel), és meg kell néznie, mi működik gyorsabban.
Lefoglalás a memóriában
Ha C-t ír, akkor tudja, hogy tetszőlegesen kis (vagy majdnem tetszőlegesen nagy) memóriamennyiséget kérhet a kupacból malloc(). Tegyük fel, hogy 30 bájt memóriára van szüksége:
char* mymemory = malloc(30);
A programozó számára úgy tűnhet, hogy Ön 30 bájt memóriát „kér” az operációs rendszertől, és visszaad egy mutatót valamilyen virtuális memóriára. De valójában malloc () csak egy C függvény, amely a függvényen belülről hív meg brk és sbrk memória kéréséhez vagy felszabadításához az operációs rendszertől.
Mindazonáltal nem hatékony minden egyes kiosztáshoz egyre több memóriát kérni; a legvalószínűbb, hogy bizonyos memóriaszegmensek már felszabadultak (free()), és újra felhasználhatjuk. malloc() meglehetősen összetett algoritmusokat valósít meg a felszabadult memória újrafelhasználására.
Van olyan, hogy a memória töredezettsége. Szélsőséges esetekben vannak kupacszegmensek, ahol csak néhány bájt kerül felhasználásra, miközben minden a kettő között fel van szabadítva (free()).
Kérjük, vegye figyelembe, hogy a memória töredezettsége hihetetlenül összetett téma, és még a programok kisebb módosításai is jelentős hatással lehetnek. A legtöbb esetben a programok nem okoznak jelentős memóriatöredezettséget, de tisztában kell lennie azzal, hogy ha a halom egyes területein töredezettség lép fel, a hatalmas oldalak ronthatják a helyzetet.
Hatalmas oldalak szelektív használata
A cikk elolvasása után eldöntötte, hogy programja mely részei profitálhatnak a hatalmas oldalak használatából, és melyek nem. Tehát egyáltalán engedélyezni kell a hatalmas oldalakat?
Szerencsére tudod használni madvise()hogy csak azokon a memóriaterületeken engedélyezze a hatalmas lapozást, ahol ez hasznos lenne.
Először ellenőrizze, hogy a hugepages madvise() módban fut-e a használatával utasítás a cikk elején.
Akkor használd madvise()hogy pontosan megmondja a kernelnek, hogy hol használja a hatalmas oldalakat.
#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)
Ne feledje, hogy ez a módszer csak tanács a kernelnek a memória kezeléséhez. Ez nem jelenti azt, hogy a kernel automatikusan hatalmas oldalakat használ egy adott memóriához.
Lásd a dokumentációt (manpage)madvisehogy többet tudjon meg a memóriakezelésről és madvise(), ennek a témának hihetetlenül meredek tanulási görbéje van. Tehát ha igazán jó akar lenni benne, készüljön fel néhány hétig az olvasásra és a tesztelésre, mielőtt bármilyen pozitív eredményt várna.