-
saxus #37 Fú, srácok, rossz végignézni, amit itt műveltek. Oké tudom, big wall of text, de...
Akkor egy kis memóriakezelés alapok, egyszerűség kedvéért maradjunk a 32 bites x86 rendszernél, bár x64 sem különbözik sokban.
Amikor elindít valaki egy programot egy modern operációs rendszeren (értsd: bármi ami a DOS-nál újabb, legyen az Win, Linux, BSD, OSX vagy akármi más) akkor annak létrejön egy virtuális memória címtere. 32 bites Windows esetén ez úgy néz ki, hogy a címteret 2 felé osztja, alsó felében garázdálkodhat a program, felső felébe kerül az operációs rendszerből a program számára elérhető rész valamint az egyéb hardverek memóriája (pl. VGA kártya, hálókártya, stb.). Az, hogy mi hova kerül a címtérben azt az eszközkezelőben az egyes eszközök tulajdonságainál az erőforrások fülön meg tudja nézni mindenki. _EZ_ a virtuális memória.
És itt jön a trükk: minden egyes memórialaphoz (a memória 4 Kb-s lapokra van felosztva) megvan az, hogy az valójában hol helyezkedik el: egy VGA kártyán, fizikai lemezen, lapozófájlban, világ másik végén egy másik számítógépben stb. Ennek kezelése részben az operációs rendszer dolga bár erősen meg van támogatva CPU oldaláról, különben elég lassú lenne. - Aki akar nézzen utána a TLB-nak.)
Ennek több haszna is van: egyrészt minden program egyedi címtérrel rendelkezik és nem függhet a másiktól. Maga az operációs rendszer akadályozza meg, hogy egyik program belenyúljon a másikába, hiszen elméletileg nem is tudhatja a másik címterét valamint maga az operációs rendszer is közbeszól.
További előny a hatékonyabb memóriakihasználás. Ha egy program lefoglal 100M ramot, valójában az történik, hogy az operációs rendszer felírja, hogy x program kért 100M ramot aztán csókolom. Egy bitet nem ad oda a programnak addig, ameddig nem használja. Viszont mivel a memória lapokra van osztva, így csak 4 Kb-s egységenként adja oda a programnak. Továbbá lehet spórolni azzal is, hogy a megosztott dolgokat (pl. .dll/.so, .exe fájlok kódja) csak egyszer tölti be a memóriába a rendszer, hiszen minden program saját virtuális memóriájában ugyanarra a valós fizikai címre mutat majd a memórialap. Meg további előnye is van a dolognak, hogy például tud 2 db 1,5 Gb-ot igénylő program futni egyszerre. (Ugye két felé van osztva a címtér, így egy program maximum 2 Gb-ot használhat egy 32 bites rendszeren. És ezért van az, hogy ha egy 32 bites gépbe berakunk 4 Gb ramot akkor az nem fog látszani mind, maximum ha PAE-val trükközünk.)
Harmadrészt átlátszó az egész egy program számára. Amikor valami miatt kikerül egy memórialap a lapozófájlba, akkor valójában az történik, hogy az operációs rendszer kiír egy memórialapot majd a virtuális memóriakezelésnél megjegyzi, hogy az a lap mostantól a lapozófájlban van és nem a memóriában. (Ha használni kell mégis azt, akkor ugye a fordítottja játszódik le.) Az egészből semmit nem vesz észre a program.
Az ilyen egyéb elvetemült dolgokat meg most szintén ne pedzegessük, hogy ennek köszönhetően lehetséges mondjuk több gépen elosztani egy program memóriáját úgy, hogy abból a program ne vegyen észre semmit. (Leszámítva, hogy ha nem készítik fel rá, lassú lesz) :)
Viszont mivel így kezeli a memóriát az operációs rendszer roppant nehéz megmondani, hogy egy program valójában mennyi memóriát is foglal. Az, amit pl. a Windows a feladatkezelőben kiír az szigorúan nézve nettó hazugság. Érdemes bekapcsolni a Working set a Private working set és a commit size (nem tudom mi a magyar feladatkezelőben a nevük) oszlopokat. Az első lesz a legmagasabb a privát a legkisebb a commit size meg valahol a félúton. Az első megmondja, hogy egy program mennyi memóriát igényelt. Ebben viszont benne van az is, ami megosztható egy másik programmal(!) valamint az is, amit még ténylegesen nem használt fel, csak allokált az oprendszertől. Alapból asszem pont ezt mutatja a feladatkezelő. Szóval nem olyan egyszerű rámondani, hogy egy program 500 megát zabál, mert abból lehet, hogy 50 megát megoszt 20 másik programmal: mert pl. azok is ugyanúgy használják az operációs rendszer ablakkezelőjét meg fájlkezelő funkcióit.
A másik érdekes témakör viszont a szabad memória témaköre. Egy modern operációs rendszeren _valójában_ a nullához közelít a szabad memória. Igen, tudom, hogy a feladatkezelő éppen azt írja, hogy 3,72 Gb foglalt a 32 Gb-ből (annyim van), de hazudik :). Valójában az operációs rendszerek minden szabad memóriát felhasználnak (legyen az Windows, Linux vagy OSX) méghozzá a lemezműveletek gyorsítására. Ha valamit be kell olvasni a lemezről, akkor azt memóriában eltárolják és hogy ha újra kell olvasni, akkor a memóriából kaparja elő és nem a lemezről. Ezért van az, hogy pl. másodjára a kedvenc játékod sok ram esetén jóval gyorsabban tölt be, mint először. Ha valaki megnyitja az erőforrás monitort, akkor ott ez szépen látszik a standby érték alatt. És miért mutatja akkor ezt szabadnak? Nos, mert valójában a programok számára szabad memória: ha egy programnak kell még ram, akkor valami ki lesz innen pucolva (lemezen úgy is megvan) és odaadja a programnak. Na meg ide jön a superfetch meg minden egyéb hasonló móka.
De alapvetően igaz: ha van szabad ram azt az oprendszerek általában felhasználják, még ha nem is veszed észre.
És mi az a lapozófájl? Nos, pont az, ami a neve: memórialapokat lehet ideiglenesen kidobálni. _NEM_ virtuális memória. Egy program számára minden memória virtuális (legyen az fizikai, az egyes eszközök memóriája vagy lapozófájl.)
Az egyes operációs rendszerek eltérő megközelítést alkalmaznak alapból de ez több mindentől is függ. Pl. még akár ugyanaz a rendszer is használhat eltérő stratégiákt 1-2 vagy 16-32G ram esetén. (Régi gépemen 4G ram mellett átlag olyan 2-2,5 Gb-ról indult az átlagos desktop környezetem, most inkább olyan 3,5 körül szokott lenni 32G mellett. Ebben mondjuk benne van az is, hogy néhány háttérfolyamat is jobban elengedi magát, mert megteheti, de ennek nem sok köze van a Windowshoz.) És ez nem azért van, mert "memleakel", hanem azért, mert van ram, megteheti. Ha valaminek úgy is sok ram kell, úgy is visszafogja magát a renszer.
(Erre egyébként jó példa a Microsoft SQL Server-e, amely saját cache mechanizmust használ és emiatt -alapból- mindig úgy foglalja magának a memóriát, hogy csak 3% szabad memóriát hagy. Többit lefoglalja magának cachenak. Akár 4 akár 12G ram van a gépben.)
Mindenesetre alapvetően a következőt tudom mondani általánosságban:
- A legtöbb Linux distrot alapból úgy állítják be, hogy amit lehet, azt tartson memóriában. Ennek előnye, hogy ha belefér a memóriába minden program, akkor nem dobálja ki a swap partícióra azokat, így gyorsan elő lehet kotorni mindent, ha kell. Két hátránya van: 1) ha elfogy a ram, akkor drasztikusan le tud törni a teljesítmény, mert hirtelen kell kipakolni mindent a lemezre. 2) ha sok a lemezművelet, amire jó lenne a sok szabad memória cachenak, akkor visszafogja a rendszer teljesítményét.
- MacOSX-re alapvetően hasonlókat lehet elmondani, mint a Linux alapból, azzal a különbséggel, hogy az OSX-et nem azért szeretjük, mert spórol a memóriával és szerintem sokkal drasztikusabban meglátszik rajta, hogy ha swaphoz nyúl. Ebbe még az a szerencsétlen eset is belejátszik, hogy az Apple hardverek jellemzően notebook alkatrészekből épülnek és ennek megfelelően notebook lemez van benne. (kivéve a MacPro, de az más kategória).
- Windowsnál alapból sokkal agresszívebben használja a lapozófájlt és valamivel konzervatívabban áll hozzá a memória kérdéséhez. Ennek, hogy ennyire használja a lapozófájlt szerintem még történelmi oka is van, ugyanis régen azért rémesen drága volt a memória és igazából olyan 2006-7 környékén kezdett nagyon letörni a RAM ára. (Vista-t is mennyien szidták, hogy fú, jaj, 1G ram kell neki minimum, - de inkább 2 - aztán a sok 512M-el rohangáló emberke meg szidta, mert nem értette meg, hogy azt a modernebb gépekre írták. Azóta meg lement a RAM ára és W7 alá meg szórjuk, mint az állat, pedig a rendszer memóriaigénye nem változott :) Na de Windows lapozófájl. Szóval a Windows ilyen szempontból adaptív jószág és ha úgy látja, hogy egy memóriarészt tényleg ritkán használ valami, akkor inkább kirakja üresjáratban a lemezre. Ennek előnye, hogy valamivel kiegyensúlyozottabb teljesítményt ad - több memória marad a lemezműveletek gyorsítására, ha egy programnak sok ram kell, hamarább tudja kiszolgálni, később jön el a csúnya letörés, mint ami OSX-en hamar mellbe tudja vágni. Hátránya értelem szerűen az, hogy valamivel többet mozgatja a lemezt és a ritkán futó vagy régen nem használt dolgok ha hirtelen kellenek, akkor lassabb előkaparni.
És hogy melyik hozzáállás a jobb? Nos, nem törnék pálcát egyik felett sem: helyzettől és felhasználás módjától függ.