<div dir="ltr"><div dir="ltr"><div>Dobrá práce, máš můj obdiv. <br></div><div><br></div><div>Zeptám se myslíš, že v Proxmoxu narazili na podobný problém? <br></div><div>Přeci jen je to LXC & ZFS a cgroups? Určitě jsou tam aplikace, které také používají mmap, ne? Několikrát jsem četl, že hodně lidí mmap doporučuje ideálně pro velké soubory.</div><div>např. <br></div><div>tady <a href="https://blog.askesis.pl/post/2019/02/mmap.html">https://blog.askesis.pl/post/2019/02/mmap.html</a></div><div><a href="https://stackoverflow.com/questions/258091/when-should-i-use-mmap-for-file-access/2895799">https://stackoverflow.com/questions/258091/when-should-i-use-mmap-for-file-access/2895799</a></div><div><br></div><div>Zdenek pripravto<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">čt 13. 8. 2020 v 14:22 odesílatel Ondrej Beranek <<a href="mailto:rainbof@gmail.com">rainbof@gmail.com</a>> napsal:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Poutave vysvetleni, dobra prace diky.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">čt 13. 8. 2020 v 13:02 odesílatel Pavel Snajdr <<a href="mailto:snajpa@snajpa.net" target="_blank">snajpa@snajpa.net</a>> napsal:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Ahojte,<br>
<br>
sliboval jsem (vetsinou off-list), ze shnu pak resenici s pameti na <br>
vpsAdminOS, tak tady to je :)<br>
<br>
Kdyz chce programator dneska z aplikace pracovat s velkym souborem, je <br>
docela rozsirenym pristupem, si takovy soubor namapovat do pameti pomoci <br>
mmap(2) syscallu.<br>
<br>
To zpusobi, ze se soubor ocitne ve virtualnim pametovem prostoru <br>
procesu, tj. ten program si pak muze sahat do toho souboru prostym <br>
pristupovanim do pameti (nabizi se teda snadny ukladani napr. Cckovych <br>
structu do souboru, pristup pres pointerovou aritmetiku, atd.).<br>
<br>
Linux cachuje takovy napamovany soubor po strankach, protoze samotnou <br>
pamet spravuje po strankach (1 stranka pameti je na x64 velka 4 kB, huge <br>
pages jsou potom dalsi extra story na jindy...). Jakmile aplikace chce <br>
precist nejaka data, Linux na pozadi, pokud uz to neudelal, pro ta data <br>
alokuje stranku fyzicke pameti, aby ta data mela realne, kde sedet, <br>
precte je do te stranky z disku (nebo kde ten soubor je) a pak tu <br>
stranku namapuje do prislusneho mista virtualniho pametoveho prostoru <br>
naseho procesu, ktery ta data cte.<br>
<br>
Jadro vede mapovane stranky v evidenci pomoci LRU listu, coz je datova <br>
struktura, seznam, ktery se vyznacuje tim, ze vede v evidenci, ktera <br>
polozka byla pouzita naposled (tak, ze se meni pri jejim pouziti jeji <br>
poradi na zacatek seznamu).<br>
<br>
Kdyz vsechno funguje jak ma, v realne fyzicke pameti jsou pouzivana <br>
ctena data a jeste nezapsane "pospinene" (dirty) stranky, do kterych se <br>
psalo, tj. je u nich naplanovano, aby se co nejrychleji dostaly na disk <br>
(pokud teda cely soubor nebyl otevreny s flagem O_SYNC, nebo podobne, co <br>
by vynutilo kazdou zmenu zapsat na disk ihned, nez Linux vrati kontrolu <br>
aplikaci pri tom zapisu do mapovaneho souboru; to neni tak caste a to je <br>
nam ted "jedno").<br>
<br>
Zapis je nastesti vyreseny dobre, Linux ma na to mechanismus, kteremu <br>
rika "writeback throttle"; kdyz detekuje, ze se zacina RAM plnit vic, <br>
nez je zdravo, zacne aplikaci ty zapisujici pristupy adekvatne <br>
zpomalovat. Tohle "impedancni prizpusobeni" funguje vcelku dobre, navic <br>
funguje dostatecne dobre i pod memory cgroup.<br>
<br>
Memory cgroup je mechanismus, kterym omezujeme pridelenou pamet <br>
kontejnerum pod Linuxem - je to volitelna sada dalsich pocitadel vyuziti <br>
pameti, nad zakladni systemove, plus vydeleni ukazatelu na LRU, <br>
writeback a dalsi cache, aby se dalo pekne vest takovehle seznamy <br>
stranek v oddelene, mimojine aby bylo jasne, co komu patri, kdyz dojde <br>
cas tu pamet jednou odklidit. Ale taky, aby se dalo hlidat maximalni <br>
vyuziti pameti na ruzne caches - zdaleka nejen - kvuli prave mapovanym <br>
souborum.<br>
<br>
Potud vsechno dobre.<br>
<br>
To nam tak system nabehne, pospousti se na nem stovka VPSek, vsechny <br>
aplikace se krasne rozbehnou, nektere si namapujou soubory, nektere do <br>
nich vesele zapisuji data...<br>
<br>
System muze bezet klidne mesice bez problemu, vsechno stiha, v pohode. <br>
Ty seznamy jsou bezne docela kratke, takze sbirka jadernych threadu <br>
"kswapd" je na pozadi pekne stiha prochazet a odklizet, jak se postupne <br>
nektere memory cgroupy dostavaji s pameti do uzkych.<br>
<br>
Koneckoncu, 4 GB RAM (na jeden kontejner) prelozeno na 4 kB stranky <br>
znamena teoretickou maximalni delku jednoho seznamu 1M polozek. To se na <br>
2+ gigahertzovych CPU preci stihne projit rychle, ze.<br>
<br>
No a pak se stane, ze po treba dvou mesicich behu systemu najednou <br>
zoufaly clen pise, ze mu v kontejneru dochazi pamet, pritom at pocita, <br>
jak pocita, nemuze se dopocitat, ze by to zabiraly aplikace - je videt, <br>
ze je to tim, ze caches nechteji odcouvavat.<br>
<br>
Hm, docela spatenka, jak to mame opravit, kdyz to trva tak dlouho, nez <br>
se problem projevi? :-D<br>
<br>
Tady nekde bych mel podotknout, ze abych byl schopny to takhle pekne <br>
vysvetlit, musel jsem doprojit celou cestu do vyresena, takze ted se to <br>
jevi zpetne jako trivka, ale nez jsem prisel na to, z ktere strany ten <br>
problem pujde aspon nejak resit...<br>
<br>
Kdyz se clovek na takovy trpici system prihlasi, vidi tam zpravidla <br>
kswapd0 na 100% a kdyz ma ta masina dva fyzicke CPU, tak tam vidi <br>
vetsinou i kswapd1 v tom samem stavu.<br>
<br>
V dmesgu jsou videt out of memory hlasky z jednotlivych kontejneru, jak <br>
narazeji na neodkliditelne caches a jadro zoufale zabiji stare procesy, <br>
aby udelalo misto pro dalsi.<br>
<br>
V tech OOM hlaskach je videt pokazde i stack trace, odkud ta OOM udalost <br>
z jadra prisla - vetsina z nich byla vyvolana kvuli cteni do mmaped <br>
souboru, coz se pozna tak, ze v tom stacku jsou videt funkce pridavajici <br>
LRU stranky na seznam te memory cgroupe.<br>
<br>
Tak si rikam, hm, to ma preci snadne reseni, nebudeme uctovat mapovanou <br>
pamet do memory cgroup clenu, ale nechame ji v root memory cgroup...<br>
<br>
Okay, to by mohlo fungovat, ze?<br>
<br>
..a zase, kswapd0/1 na 100%...<br>
<br>
To uz jsem se zacal seriozneji zajimat, co se to vlastne deje, co delaji <br>
tak dlouho a jak to cele funguje, kdyz to neslo smaznout "izy hackem".<br>
<br>
Napad to byl dobry, fungoval by, nebyt mensi drobnosti:<br>
<br>
kswapd, kdyz odklizeji caches na pozadi, prohledavaji memory cgroupy <br>
stylem "dej mi takovou, ktera zere nejvic a tu odklidime, kdyz to nebude <br>
stacit, pujdem na dalsi".<br>
<br>
Tj. pokud se objevi jedna cgroup, ktera je vetsi a ma toho vzdycky vic k <br>
odklizeni, muze se vzdycky kswapd zahojit na ni a k dalsim se ani <br>
nedostat.<br>
<br>
Jedine, kdy se odklizi pamet uplne primo z te memory cgroupy, je tzv. <br>
"direct reclaim", cesta kodu primo v momente, kdy je potreba alokovat - <br>
ale v tu chvili neni tolik casu na uklizeni, tak se jadro zas tak <br>
nesnazi a nekdy to muze vzdat predcasne a rict, ze pamet nenaslo a <br>
vyvola OOM situaci v postizene memory cgroupe.<br>
<br>
Hmm... okay, takhle by to neslo, tak zkusme mmaped pamet neuctovat <br>
cgroupam vubec a nechme ji v zakladnich systemovych seznamech...<br>
<br>
A po trochu zapaseni, bo se v jadre s memory cgroup nepocita, ze by <br>
nahodou mmaped pamet nebyla uctovana zadne memory cgroupe, je vyreseno, <br>
odchod na parek!<br>
<br>
...do chvile, nez tim posleme celou masinu out-of-memory a OOM chyby <br>
zacnou prichazet odkudkoliv, ne jen z mmaped readu odzpod z <br>
mem-cgroup...<br>
<br>
Totiz kdyz byly mmaped soubory uctovany na jeden seznam, ktery neni v <br>
memory cgroupe, myslelo si jadro, ze ma hodne volnou ruku v tom, co si <br>
muze dovolit nechat nacachovane - ale v tom je potom mensi caveat se <br>
ZFS... postupny nahodny random access pattern k datum mmaped souboru <br>
nadela z ARC slab caches fragmentovane reseto, jeste kdyz se drzi ty <br>
kousky z tech puvodne nactenych dat pri zivote "pripinovanim" na jeden <br>
velky seznam, ktery nema duvod couvat, protoze host ma preci vsechnu <br>
pamet k dispozici bez limitu :D<br>
<br>
No pak a chudaci kswapd, kdyz si s tim bordelem maji nejak poradit a <br>
odklidit to, *obzvlast* kdyz jsou jen dva a kdyz pod nima mame (konecne <br>
spravne nastavene se spravnym ashiftem) NVMe pole... na te staging node <br>
(nyni node1.stg) se tak darilo zaplnit RAM az skoro do mrtva.<br>
<br>
Takze co s tim? :)<br>
<br>
Snadna reseni dosla, bude potreba odklizet ty seznamy <br>
per-limitovana-memory-cgroup.<br>
<br>
Na nekolik iteraci jsem nakonec dospel k patchi, ktery spusti <br>
per-NUMA-node "ksoftlimd" thready, pro kazdou memory cgroupu, ktera ma <br>
nastaveny soft_limit.<br>
<br>
Ksoftlimd pak dela presne toto - prochazi seznamy svoji memory cgroupy a <br>
drzi si je okolo soft_limitu.<br>
<br>
Kswapd maji o praci s memory cgroupama min, pokud je jadro nastavene v <br>
rezimu, ze ma ksoftlimd poustet automaticky (da se tez spoustet jen <br>
rucne).<br>
<br>
My jsme zatim defaultne zvolili soft_limit jako watermark, nad ktery se <br>
ma ksoftlimd snazit vic odklizet, nastavujeme ho na 80% pameti <br>
kontejneru - ale do budoucna mozna tohle jeste predelam na nejakou vetsi <br>
automatiku, podle toho, jak kde se ukazou pripadne nedostatky.<br>
<br>
Tedy, vysledna situace je, ze pokud aplikace zerou min, jak 80% pameti, <br>
ale je co drzet v RAM jako cache, bude mit kontejner vyuzito okolo tech <br>
80% - bude to videt normalne jako aplikacni pamet a zbytek jako caches. <br>
Uz by se nemelo stat, ze vyuziti stoupne az ke 100% kvuli caches a ze <br>
dojde k OOM a zabijeni procesu.<br>
<br>
Zaverem bych jeste zminil ty patche:<br>
<br>
Pokus mmaped soubory nauctovat root mem cgroupe:<br>
<br>
<a href="https://github.com/vpsfreecz/linux/commit/d42232f89795" rel="noreferrer" target="_blank">https://github.com/vpsfreecz/linux/commit/d42232f89795</a><br>
<br>
Pokus mmaped soubory mem cgroupam neuctovat vubec (popis commitu je blbe <br>
a celkove je nedocisteny, nebyl jsem s tim spokojeny a nechtel jsem tim <br>
travit vic casu, radsi jsem koumal, co dal, at the time...) -><br>
<br>
<a href="https://github.com/vpsfreecz/linux/commit/c10ae4a7ef95" rel="noreferrer" target="_blank">https://github.com/vpsfreecz/linux/commit/c10ae4a7ef95</a><br>
<br>
A finalne, aktualne nasazena verze ksoftlimd patche:<br>
<br>
<a href="https://github.com/vpsfreecz/linux/commit/e04b3f9cda1d" rel="noreferrer" target="_blank">https://github.com/vpsfreecz/linux/commit/e04b3f9cda1d</a><br>
<br>
A uplne-uplne zaverem: linux kernel neni advanced black magic. Je to jen <br>
strasne velka a nekdy dost neforemna kupa C kodu, ktery potrebuje <br>
schopne a ochotne instalatery.<br>
<br>
V koncinach memory cgroup + memory managementu je teda hodne, co <br>
zlepsovat, a vubec to neni raketova veda... Teda obecne, na <br>
kontejnerizace v Linuxu je dost co resit.<br>
<br>
Takze kdybyste s tim jadernym vyvojem nekdo chtel pomoct, stavte se na <br>
IRC, nebo v Base48 v Brne pokecat, neco vymyslime, bude to zabava, trust <br>
me ;)<br>
<br>
/snajpa<br>
_______________________________________________<br>
Community-list mailing list<br>
<a href="mailto:Community-list@lists.vpsfree.cz" target="_blank">Community-list@lists.vpsfree.cz</a><br>
<a href="http://lists.vpsfree.cz/listinfo/community-list" rel="noreferrer" target="_blank">http://lists.vpsfree.cz/listinfo/community-list</a><br>
</blockquote></div>
_______________________________________________<br>
Community-list mailing list<br>
<a href="mailto:Community-list@lists.vpsfree.cz" target="_blank">Community-list@lists.vpsfree.cz</a><br>
<a href="http://lists.vpsfree.cz/listinfo/community-list" rel="noreferrer" target="_blank">http://lists.vpsfree.cz/listinfo/community-list</a><br>
</blockquote></div><br></div>