Teraz vám prinášame trošku technicky náročnejší článok o problematike s ktorou sa museli naši admini vysporiadať.
Veľmi zjednodušene môžeme rozdeliť pamäť v Linuxe na 2 typy:
- mapped – aplikácie – stack, data, loadnuté knižnice, alokovaná pamäť za behu app, …
- unmapped – page cache (disková cache) – cacheujú sa tam súbory pri čítaní/zápise na disky, rieši to kernel nezávisle od aplikácií
- (a ešte máme nejaké ďalšie ako slab, kde sú TCP/IP stack buffre, directory entries, atď.)
Page cache je v Linuxe nie najlepšie implementovaná.
Jeden z problémov, ktoré ma trápia, je napríklad to, že jeden task pri zápise alebo načítaní veľkého množstva dát odstráni z page cache všetko ostatné a nahradí to tým, čo číta/zapisuje.
Na desktope to tak nevadí.
Predstavme si ale vyťažený server, kde pristupujú stovky klientov a každý jeden démon, na ktorý je pripojený klient, číta iné dáta z disku a masívne sa tam využívajú nacachované data.
Zrazu sa spustí nejaký backup alebo iná aplikácia a začne robiť s objemným množstvom dát.
Stane sa to, že sa dáta potrebné pre tie démony z page cache odstránia, následne démony čakajú na IO z diskov, lebo nemajú dáta nacachované, server laguje a je to pekne v **** 🙂
Ukážka, server zo 16 GB RAM, vytvoríme 6 GB file, zmažeme ho a pozrieme sa na pamäť:
# dd if=/dev/zero of=foo bs=1M count=6144 6144+0 records in 6144+0 records out 6442450944 bytes (6.4 GB) copied, 67.489 seconds, 95.5 MB/s # free -m total used free shared buffers cached Mem: 15928 15872 55 0 0 12946 -/+ buffers/cache: 2926 13001 Swap: 949 520 428 # rm foo # free -m total used free shared buffers cached Mem: 15928 9630 6297 0 0 6865 -/+ buffers/cache: 2765 13163 Swap: 949 520 428
Ako môžete vidieť – 6GB nám zmizlo z cached a je free.
Vytvorenie 6GB súboru nám odstránilo z cache 6GB nacachovaných dát a následne zmazanie súboru uvoľnilo pamäť z page cache.
V Linuxe už dlho existuje nejaké limitovanie pamäte pre procesy (syscall setrlimit()), napr. builtin príkaz ulimit v shelloch, alebo pam v /etc/security/limits.conf (hlavne pre užívateľov, ktorí sa prihlásia).
To nám ale limituje iba mapped pamäť, nie page cache. Môžete aplikáciu olimitovať povedzme na 100 MB, ale aj tak pri čítaní/zápise veľkého množstva dát vám odcachuje potrebné dáta z page cache.
V nových kerneloch nám pribudla pekná featura tzv. control groups, pomocou nej môžeme nastaviť pre rôzne procesy limity na celkovú použitú pamäť.
Teda mapped aj unmapped, taktiež nastaviť iba konkrétne CPU pri smp systémoch, kde majú dané procesy bežať.
Kernel v Ubuntu má všetko čo je treba, tak si to poďme rovno ukázať, ako sa to konfiguruje.
# mkdir /cgroup
# mount -t cgroup -o cpuset,memory none /cgroup
Týmto sme namountovali hlavnú cgroupu, kde sú všetky procesy.
V /cgroup/tasks je zoznam pidov.
# cat /cgroup/cpuset.cpus 0-3 <--- 2 CPU po 2 jadrá, teda 4 jadrá dokopy. # cat /cgroup/cpuset.mems 0-1<--- iba pri numa systémoch, každé CPU má vlastnú pamäť, majú to hlavne Opterony, ale sú aj Xeony z numa podporou.
Vytvoríme si novú cgroup pomocou mkdir
# mkdir /cgroup/test (tu sa nam objavia automaticky vsetky subory ako v /cgroup/) Teraz musíme nastaviť CPU a pamäť, lebo defaultne ma nová cgroupa všetko prázdne. # cat /cgroup/cpuset.cpus >/cgroup/test/cpuset.cpus # cat /cgroup/cpuset.mems >/cgroup/test/cpuset.mems Olimitujeme túto cgroupu na 128 MB RAM. # echo 128M >/cgroup/test/memory.limit_in_bytes Hodíme pid bashu, s ktorým robíme do novej cgroupy, všetky novovytvorené child procesy budú automaticky v tejto cgroupe. # echo $$ >/cgroup/test/tasks vytvoríme 6GB file # dd if=/dev/zero of=foo bs=1M count=6144 6144+0 records in 6144+0 records out 6442450944 bytes (6.4 GB) copied, 108.919 seconds, 59.1 MB/s # free -m total used free shared buffers cached Mem: 15928 15696 231 0 0 13417 -/+ buffers/cache: 2278 13649 Swap: 949 556 392 # rm foo # free -m total used free shared buffers cached Mem: 15928 15553 374 0 0 13291 -/+ buffers/cache: 2262 13665 Swap: 949 556 392
Voila, dd nám nezmazalo 6 GB z page cache, ale bolo limitované na 128 MB RAM a v prípade, že aplikácia prekročí sama nastavený limit pamäti (nie page cache), tak ju killne OOM killer.
Môžeme ju zrušiť
# rmdir /cgroup/test rmdir: /cgroup/test: Device or resource busy Samozrejme sa nedá, lebo tam máme bash, tak ho najskôr prehodíme do hlavnej cgroupy # echo $$ >/cgroup/tasks # rmdir /cgroup/test
Page cache je stále zle vyriešené, ale toto je aspoň niečo, čím môžeme olimitovať rôzne aplikácie na serveri.
Ďalšou zaujímavou vecou v cgroups, ktorá ešte nie je priamo v kerneli, je bio-cgroup + dm-ioband – tým sa dá limitovať I/O bandwith, ale netestoval som.
Existujú aj nejaké userspace tooly, ale neskúšal som ani jeden. Niekde na Fedora stránke som videl, že majú aj pam modul pre cgroups, netestoval som ho.
4 odpovede na “Linux page cache a control groups”
hmm… necital som to na blackhole? 🙂
😀 vyzera to tak, vsimni si ze toto je „cenzurovana“ ver. :>
Ktory kernel dokaze vytvorit cgroup? Alebo je to iba feature ubuntu? Na centOS distro, kernel 2.6.18 mi to nefunguje.
nie je to feature ubuntu, ale control groups sa nachadza v kernel verzii 2.6.24 a novsich, 2.6.18 to este nema