Értsük meg a swappiness működését

Tux

Tudom, hogy egy kicsit megcsúsztam a release hétfővel, amiért (főleg a rendszerességet szeretőktől) elnézést is szeretnék kérni. Remélem, hogy a cikk tartalma kárpótolni fog a késésért.

Számomra igencsak meglepő volt, hogy a többi cikkhez képest, relatív nagy népszerűségnek örvendett az „Értsük meg a Load average értékét!” írásom. Nos, ennek mintájára megpróbálom érthetően elmagyarázni, hogy mi is az a swappiness, mire való és miért (nem) érdemes piszkálni.

A fő gond: nincs olyan, hogy túl sok memória

”640 Kbyte mindenre elég lesz.” Szól a híres, sokat emlegetett mondás. Nekem is volt egy hasonló mondásom: „Az asztali gépemben 3-4 évig biztosan elég lesz a 8 GB RAM.” Mindketten tévedtünk. Ugyanis alig három hete szembesültem vele, hogy az Oracle minta virtuális rendszer „mindössze” 6 GB memóriát követel minimum…, így csak 2 GB maradt a rendszernek és az ügyes-bajos dolgaimnak. Ennek a vége pedig – mint az várható –, swappolás lett.

Az alapok

Mielőtt azonban a lényegre térnék, szeretném röviden ismertetni az alapokat, amivel jobban megérthetjük az egész működését. Ha nem érdekel és/vagy tisztában vagy velük, akkor nyugodtan ugorhatsz a „Swap → Swappiness” részhez.

Az operációs rendszerek nap-mint-nap azzal szembesülnek, hogy gazdaságosan kellene minden falánk programnak kiosztani a rendelkezésre álló, sokszor túl kevés memóriát. Ahhoz, hogy a program is fusson, és a felhasználó is boldog legyen, a kernelnek hazudoznia kell. Minden programnak odaígéri a kért memória mennyiséget, akár valóban elérhető, akár nem. Ha nem, akkor abban reménykedik, hogy a program csak túl sokat kér és ennek csak egy részét fogja valójában csak használni, így az odaígért terület egy részét valójában nem is kell neki odaadni. Ennek a kamuzásnak neve is van: overcommit. Maga az overcommit ismertetése is megérdemelne egy külön cikket (ugyanis állítható, hogy „mekkorát” kamuzzon a kernel), most túl sokat nem kívánok vele foglalkozni, legyen elég annyi, hogy igazán mókás, amikor őszintén alig bír megmoccanni a rendszer. :)

Talán meglepő, de ez a füllentés elég jól működik ahhoz, hogy egy igen jól bevált módszer legyen. Egyrészt sokszor fordul elő, hogy mire az adott programnak a lefoglalt(nak hitt) területre szüksége lenne, addigra a kernel valóban oda tudja azt neki adni, mert egy másik program befejezte a futását, és az így felszabadult memóriaterület bevethető lett. Másrészről a kernel helyet csinálhat a memóriában az új adatoknak. Ezt teheti úgy, hogy eldobja a különböző gyorsítótárakat vagy a memóriában lévő, régen használt adatokat kiírhatja a lemezre. Ezt hívjuk lapozásnak.

Lapoz? Hogy mondod?

A memóriát az operációs rendszerek úgynevezett lapokra vagy szeletekre osztják fel. Ezek a lapok alapértelmezett esetben fixen 4 KiB méretűek és a lehetséges méretük erősen CPU-architektúra függő, azonban a 4 KiB igen általános. Linux esetén ez az érték a include/asm-generic/page.h állományban, a PAGE_SHIFT konstansban van tárolva. A memóriában laponként lehet foglalni, azaz hiába foglalsz csak 1 KiB memóriát, egy teljes lap le lesz foglalva, azaz lesz 3 KiB veszteséged. Így, első hallásra ez elég rosszul hangzik. Azonban ez a kis pazarlás megéri a kezelhetőséget.

/* PAGE_SHIFT determines the page size */
 
#define PAGE_SHIFT	12

include/asm-generic/page.h 13-15. sor

Összerázva

A lapozási terület az a hely, ahova a kernel a ritkán használt memórialapokat kihelyezi. Ez történhet fájl(ok)ba (lapozófájl, ismerős valahonnan?) vagy partíció(k)ra. A lapozás pedig nem más, mint a memóriában lévő, régen használt adatok lapozási területre történő kiírása. Találkozhattál vele swappolás néven is. No de honnan tudja a kernel, hogy mit érdemes kilapozni? Karbantart egy listát, amiben számon tartja a lapok hozzáférését. Ha úgy ítéli meg, hogy a memórialapot érdemes kihelyezni a lapozási területre, akkor megteszi. A helyét pedig feltöltheti pl. gyorsítótárral. Honnan tudhatod, hogy egy program (részben) ki lett lapozva? Volt már olyan, hogy megnyitottad mondjuk a GEditet, majd úgy maradt, órákra? Egyszer csak eszedbe jutott, hogy kellene belőle valami, de viszonylag nehézkesen és lassan állt helyre? Nos, a kernel észlelte, hogy a GEdit-hez egy jó ideje már nem nyúltál, ezért úgy gondolta, hogy a helyét feltölti valami hasznosabbal. Nagyon helyesen. :)

Swappogó kernelt hamarabb utolérik, mint a sánta kutyát

Így első olvasatra, egész jó dolognak tűnik a lapozófájl használata, hiszen segítségével a szűkös RAM-unkat bővíthetjük általunk megadott tárhellyel. Azonban, mint említettem a kilapozás a háttértárra történik (Na jó, nem mindig… Van úgy, hogy zswappal a memóriába lapozunk vagy CUDA-val a VGA memóriájába stb., de ezek nem általánosak). Jobb esetben SSD-re, rosszabb esetben szegény vasreszelék pörgetőre (HDD). Ezek pedig jócskán lassabbak az operatív tárnál, azaz fehér ember várni homokóra…

Swap → Swappiness aka. Lapozófájl → Lapozási hajlandóság

A swappiness beállítás célja, hogy mindenki az igényeinek megfelelően tudja hangolni a kernel lapozási hajlandóságát, azaz mekkora memóriafoglaltságnál érezze a késztetést a kilapozásra. Lehetséges értékei 0-tól 100-ig terjedő, egész számok. Minél kisebb ez az érték, a kernel annál kevésbé hajlandó lapozni.

Szükségem van erre?

Attól függ, mire használod a géped, és az milyen képességekkel rendelkezik. Ha fejlesztő vagy, van 16 GB memóriád, és a használt fejlesztői környezeted minden indok nélkül olykor-olykor pár pillanatra irreszponzívvá válik, jó eséllyel a túl magas swappiness érték miatt az IDE bizonyos részei bekerültek a swapba. Ha kevés memóriád van és nem zavar ha a rendszer egy-egy programot lassabban indít és zár be, azért cserébe, hogy ha egyszer betöltött, akkor kielégítő sebességgel fut a program, akkor a magasabb swappiness érték lehet a barátod.

Melyik értékeket szeressem?

Megmondom őszintén, hogy azért késett a cikk megjelenése, mert közelebbről szerettem volna megismertetni veled, kedves olvasó, a swappiness értékét. Írtam erre egy memóriafoglaló, felszabadító, közben méricskélő programot is (C-ben, mi másban… érdekes nyelv, egyszer talán megírom a véleményemet róla). Azonban az eredmények elemzésekor egymásnak ellentmondó adatokat kaptam, amik se a Linux kernel dokumentációval, sem magával a forráskóddal nem voltak szinkronban. Így jelenleg gondolkodok, hogy mi lehet a gond és/vagy mit nem vettem figyelembe. Ha rájövök, hol a gond, akkor jó eséllyel lesz egy másik cikk is, csak az eredményekről.

Charmed a 10-es értékre esküszik, szerinte érezhetően reszponzívabb vele a gép, mint az alapértelmezett 60-assal. Bár ő ugyanezt mondta a Deadline → CFQ váltáskor is, ami fura, mert én pont fordítva érzem ott is. Számomra az alapértelmezett 60-as swappiness érték tökéletes, sőt olykor-olykor eszembe jut, hogy növeljem. Ami még viccesebb a dologban, hogy ugyanúgy, 8 GB memóriával gazdálkodunk és mindketten aktívan kihasználjuk a benne rejlő lehetőségeket.

Próbálkozz nyugodtan! Nem lehet elrontani, ameddig nem rögzíted, addig az alapértelmezett érték minden újraindítás után visszaáll. Ha soknak érzed az alap 60-as értéket, csökkentsd 10-re. Ha kevésnek, legyen 90! Amire figyelj: a swappiness 0 értéke azt jelenti, hogy a kernel csak és kizárólag akkor nyúl a lapozófájlhoz, ha el akarja kerülni az OOM helyzetet, azaz megakadályozni, hogy teljesen kifogyj a memóriából.

Utoljára, de nem utolsó sorban, ugye be is szeretnéd állítani a szimpatikus értéket. Most pofátlan leszek, és azt mondom, hogy nézd meg a kapcsolódó kisokosunkat: Swappiness érték beállítása

Kellemes kísérletezgetést!