( egeresz | 2012. 11. 05., h – 18:18 )

Ismét volt rá egy kis időm.

Tesztkörnyezet:
debian 6.0.5, 2.6.32-5-amd64
4 x Opteron 6238 (total 48 cores)
256GiB ram
Numa:
8 memory node
cpuset konfig: minden cpu -ra egy cpuset (tehát 2 memory node 1 cpuset)
64 GiB /cpuset

megjegyzések
Az alábbi fogalmak a linux kernelben egymástol függetlenek, az algoritmusuk nincs összehangolva.

overcommit
Hogy a processz kaphat-e több memóriát a malloc() hatására, mint amennyi ténylegesen rendelkezésre áll. A vm.overcommit_memory és a vm.overcommit_ratio *nem* kapcsolja ki az overcommitot, csak egy felső határt adhatsz neki. Semmi fogalma nincs a cpuset -ről.
OOM esemény
Ha egyszercsak kiderül, hogy overcommit volt, és az hiba volt (elfogyott a memória). Ekkor oom_killer van, vagy panic. (vm.panic_on_oom) Az oom_killer elindul, ha lap kellene, de ténylegesen már nincs. Akkor is elindul, ha csak egy cpuset-ben fogy el a memória.
cpuset
Limitálhatod egy processz cpu és memóriahasználatát valamely subsetre. Ez, valójában a process (resident size) working set -jét limitálja, nem a "memóriáját" ami nem túl definit.
resident set, resident set size, rss, working set
A processz memórájából az a rész, ami a fizikai memórában éppen aktuálisan a processzhez van mappelve, és ezt a területet a processz laphiba esemény (page fault exception) nélkül éri el. Általában working set -nek hívják, de pont a linuxnál gyakran resident set -nek :-) Eltérés van még aközött, hogy egy processz bemeppelt területét, vagy az összes processz bemeppelt területét hívják working set -nek. Nekem most a tesztelés során úgy tünt, hogy a cpuset a benne lévő összes processz working set-jét limitálja. See man ps, "SIZE and RSS fields"
procesz virtuális memória
Amit a programozó a programján keresztül lát. Ennek egy része benne van a working set-ben, más része az in page cache-ben, más része az out page cache-ben, vagy kint a diszken, vagy a 3rd level pagecacheben, vagy az mmapp()-elt file-ban, vagy a futtatható exe-ben, vagy másik processzel közös lapokban, vagy... baromira nem egyszerű tényleg kikapcsolni az overcommitot.

teszteléshez használt program, környezetek
írtam egy C progit, ami a paraméterében megadott mennyidégű memóriát lefoglalja, majd megtölti.
A tesztprogramnak egy kicsit nagyobb méretet adtam, mint ami a cpuset-be befér. (64GiB + 1KiB)
A tevékenységét monitoroztam a 'sar -B 1' paranccsal. (man sar)
vm.overcommit_memory:2, vm_overcommit_ratio:97

tesztesetek

mem_exclusive:0, mem_hardwall:0, swap
A 'sar -B 1' kimeneten (részlet) jól látszik, amikor megtelik a cpuset, és elkezd lapozni. Fizikai diszkre-írás történik, de nem értem ez miért nem látszik a majflt/s értéken. A program rendben lefutott.

  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
      0.00      0.00 413940.00      0.00     50.00      0.00      0.00      0.00      0.00
      0.00      0.00 413991.00      0.00     50.00      0.00      0.00      0.00      0.00
      0.00  58760.00 349209.00      0.00   6620.00  11264.00   9792.00   6357.00     30.19
  17272.00 137140.00  28572.00      2.00  30343.00  33280.00  29664.00  28658.00     45.53

Az első sorban lévő nagy fault/s érték azért van, mert a kernel akkor annyi üres lapot adott oda processznek (working set növelés). A végén elég rendes pgpgin/s pgpgout/s érték van, a swap disk 100% -on ment. (ellenőrizve 'sar -d 1' -gyel)

mem_exclusive:0, mem_hardwall:0, no swap
OOM esemény történt, az oom_killer elindult, és szerencsére ezt a processzt találta meg. 6-7 sec teljes megakadás után a rendszer újra magához tért. A tesztprogram ki lett lőve.
mem_exclusive:1, mem_hardwall:1, swap
Nem láttam látható és érzékelhető különbséget az első esethez képest.
mem_exclusive:1, mem_hardwall:1, no swap

nem látható eltérés a korábbi 'no swap' konfighoz képest. Az oom_killer elindult, a rendszer kicsit állt, majd az oom_killer megtalálta ezt a processzt és kilötte.

Javaslat

  • Legyen swap.
  • Olyan queue rendszert/shedulert kell használni, ami képes a memóriát osztható és felhasználható erőforrásnak tekinteni (consumable resources) A felhasználókat kötelezni kell az igényelt memória megadására. A job inditásakor be kell állítani (ulimit -v) a felhasználható memóriát. Ez persze csak akkor működik, ha a queue rendszer képes megérteni a cpuset-ek topológiáját.