.NET szemétgyűjtés – 6.
- Az újabb objektum rövidebb ideig él
- A régebbi objektum hosszabb ideig él
- A memóriaterület egy kisebb részén a szemétgyűjtés sokkal gyorsabb, mintha azt az egész területen tennénk
Amikor inicializálódik egy menedzselt heap terület (mondjuk az alkalmazás indulásakor), akkor még nem tartalmaz objektumokat. Amikor létrejön egy új objektum, akkor az kezdetben a 0. generációba tartozik, és a 0. generációnak fenntartott memóriaterületre vagy listába kerül. Kezdetben a 0. generációs lista mérete mondjuk 256 KB (többnyire a CPU L2 cache-hez igazítva, de ez változtatható).
A fenti ábrán láthtó, hogy A – E objektumok vannak a 0. generációban, de a C és E már nem használt, azaz elpusztítható. Amikor egy újonnan létrehozott, mondjuk F objektum miatt a mérete éppen meghaladná a generációs lista korlátját, akkor a szemétgyűjtő elindul. Ezt követően észleli, hogy a C és E már nem kell és eltakarítja őket, majd összetömöríti a listát, így a D objektum közvetlenül a B után kerül. A szemétgyűjtést túlélő A, B és D objektumok úgymond "öregszenek", ezért átkerülnek az 1. generációs listába (a 0. generációból törlődnek), míg az újonnan létrejött "fiatal" F objektum pedig bekerül a 0. generációs listába, ahogy a lenti ábrán ez jól észlelhető.
Az élet persze megy tovább. Újabb és újabb objektumok jönnek létre mondjuk G, H, I, J és K néven, majd a már ismet módszer szerint azok is bekerülnek a 0. generációs listába (elvégre fiataloké a jövő vagy mi a szösz).
Ahogy telik-múlik az idő, tegyük fel, hogy a B, H és J objektumok érvénytelenné és így feleslegessé válnak. A fenti ábra már ezt az áldatlan állapotot mutatja. Mondjuk, hogy eközben új objektum keletkezik L néven, és bekopogtat a 0. generációs lista ajtaján. Ők azonban kiüvöltenek neki az ajtón keresztül, hogy "Hékás, tele van a 256 kilóbájtunk, menj a sunyiba!" Erre a civakodásra a szemétgyűjtő is felkapja a fejét és odaszól a 0. generációnak, hogy "Hohohó, nem úgy van az!", majd iziben nekilódul, hogy rendet vágjon az elkanászkodott fiatalok között. Mielőtt azonban tovább haladnánk a történetben, megállunk egy pillanatra és szögezzük le, hogy az 1. generációs lista mérete kezdetben mondjuk 2 MB azért, hogy a középkorú objektumos hölgyek és urak is kényelmesen elférjenek benne (megjegyzem ez a mese szempontjából később még fontos infomácó lehet).
No, de ott tartottunk, hogy betelt a 0. generációs lista, és emiatt a szemétgyűjtő elindult a szokásos útjára. Ekkor az 1. generációban még volt elég szabad hely, így a szemétgyűjtő őt nem bántja, csak a 0. generáció környékén kezd el szaglászni. Többek között azért, mert mint írtam, az a fixa ideája, hogy a 0. genrációban élő új objektumok tartanak ki a legrövidebb ideig, ezért is érdemes velük kezdedni a sort. Az 1. generációban lévőket tehát (bár lenne mit gyűjtögetni ott is) egylőre életben hagyja, de nem pusztán jóindulatból, hanem teljesítmény okokból. Ha nem muszály, feleslegesen nem dolgozik ő sem, és mint sejtjük a kevesebb vizsgálat rövidebb késleltetési időt jelent a folyamat futásában. Megjegyzem, ha egy objektum hivatkozik egy 1. generációba tartozó másik objektumra, akkor természetesen ő megmenekül, bárhol is tanyázik (ez fordítva is igaz, amikor egy régebbi generációban lévő objekum hivatkozik egy újabb generációban lévő másikra).
Azt csak érdekességként említem meg, hogy a Microsoft teljesítménytesztje alapján a 0. generációban végrehajtott szemétgyűjtő művelet kevesebb, mint 1 századmásodpercig tart. A cél az, hogy ez a tevékenység ne igényeljen több időt, mint egy közönséges lapváltás (page fault).
A generációs szemétgyűjtő feltételezése, hogy a hosszú életű objektumok tovább tartanak. Valószínűbb, hogy az 1. generációban lévők tartósabbak, mint a 0. generációban helyet foglaló társaik. Másképp mondva, az 1. generációban valószínűleg nem, vagy csak nagyon ritkán lenne eltakarítandó objektum, azaz felszabadítandó memóriaterület, így annak örökös zargatása tiszta időpocsékolás lenne.
A fenti ábrán látható, hogy akik a 0. generációban túlélték a szemétgyűjtést, azok átkerültek az 1. generációba, és így a 0. generáció szabadon és boldogan várja az újonnan beköltöző objektumokat. Továbbá, mivel a szemétgyűjtő nem vizsgálta az 1. generációt, így az eredetileg ott lévő, és egyébként már régóta nem használt objektumok (mint amilyen a B) érintetlenül maradtak.
A történet közepén felbukkanó L objektumot egy picit elhanyagoltuk, de ez most már így marad a következő alkalomig (a fene se gondolta, hogy ennyit fogok írni).
Most már becsszóra az utolsó következik.
Folytatjuk…
.NET szemétgyűjtés – 5.
internal class Proba{~Proba(){Program.objRefTarolo = this;GC.RegisterForFinalize(this); // Ez vagy itt van, vagy nincs…}}
public static class Program{public static object objRefTarolo;public static void Main(){Proba proba = new Proba();…}}