Najbolji primjeri iz prakse za olakšavanje odvoza smeća u .Net

U programu Microsoft.Net prikupljanje smeća mehanizam je koji je usvojilo Common Language Runtime (CLR) za čišćenje resursa koje vaša aplikacija troši. Kada kreirate objekte u .Netu, oni se pohranjuju u upravljanu hrpu. Iako trebate stvoriti objekte, u većini slučajeva ne morate biti zabrinuti zbog čišćenja predmeta - vrijeme izvršavanja to bi učinilo umjesto vas.

Međutim, trebali biste usvojiti najbolje prakse u svojoj aplikaciji kako biste olakšali odvoz smeća i pomogli bržem čišćenju resursa. Iako je .Net vješt u povraćaju upravljanih objekata, trebali biste se pridržavati određenih smjernica kako biste olakšali brže prikupljanje smeća kako biste poboljšali izvedbu svoje aplikacije. U ovom članku želio bih predstaviti raspravu o tome kako odvoz smeća funkcionira i najbolje prakse uključene u olakšavanje odvoza smeća u .Netu.

Kada se odvija odvoz smeća?

Odvoz smeća odvija se kada sustav ima malo dostupne fizičke memorije ili je GC.Collect()metoda izričito pozvana u kodu vaše aplikacije. Objekti koji se više ne koriste ili su nedostupni iz korijena kandidati su za odvoz smeća. U osnovi, sakupljač smeća čisti memoriju koju zauzimaju objekti koji nemaju reference.

Generacije

Runtime upravlja generiranom gomilom u generacije. Te generacije koristi za organiziranje kratkotrajnih i dugovječnih objekata. Treba napomenuti da sakupljač smeća radi puno češće u nižim generacijama nego u višim. Generacija 0 sadrži kratkotrajne objekte kao što su privremeni objekti. Kada se objekt stvori, on se pohranjuje u generaciju 0, osim ako nije veliki objekt. Ako je objekt veliki objekt, pohranjuje se u Veliku hrpu objekata (LOH) u generaciji 2. U većini slučajeva sakupljač smeća vraća objekte generacije 0 kada radi u pozadini.

Pri pisanju koda trebali biste se pridržavati određenih najboljih praksi. Kao primjer, trebali biste stvoriti objekte u lokalnom opsegu što je više moguće kako biste olakšali odvoz smeća. Objekti koji su stvoreni u višem opsegu općenito se duže nalaze u memoriji. Možete iskoristiti CLR profiler da biste razumjeli obrasce raspodjele vaše aplikacije.

Trebali biste izbjegavati pozivanje GC.Collect()metode jer ona uzrokuje potpunu kolekciju svih generacija (generacija 0, 1 i 2). Kada uputite poziv GC.Collect()metodi, vrijeme izvođenja posjećuje sve aktivne objekte u vašoj aplikaciji. To zahtijeva znatnu količinu vremena i stoga je vrlo skupa operacija. Kao rezultat toga, nije dobra praksa pozivati GC.Collect()metodu.

Ako morate pozvati GC.Collect()metodu, trebali biste nazvati GC.WaitForPendingFinalizers()nakon poziva kako GC.Collect()biste osigurali da trenutna izvršavajuća nit čeka da se izvrše finalizatori svih objekata.

Dalje, trebali biste GC.Collect()ponovno uputiti poziv metodi kako biste osigurali prikupljanje preostalih mrtvih predmeta. Ovi mrtvi objekti koji su mogli biti stvoreni zbog poziva metode finalizatora na objektima. Sljedeći isječak koda pokazuje kako se koriste ove metode.

System.GC.Collect();

System.GC.WaitForPendingFinalizers();

System.GC.Collect();

Trebali biste osigurati da smanjite skrivena izdvajanja i napišete kôd na takav način da se eliminiraju šanse za promociju kratkotrajnih objekata u više generacije. Ne biste trebali referencirati kratkotrajne predmete od dugovječnih kako biste izbjegli promociju kratkotrajnih objekata u više generacije.

Također biste trebali izbjegavati pisanje finalizatora za svoje predmete. Ako u svojoj klasi imate implementiran finalizator, objekti takvih klasa postat će dugovječni objekti jer runtime treba promovirati konačne objekte starijim generacijama. Trebali biste postaviti objekte na nulu prije upućivanja dugotrajnog poziva ako takvi objekti nisu potrebni aplikaciji. Ako više ne trebate statični objekt ili druge objekte u svojoj aplikaciji, trebali biste ga postaviti na nulu prije upućivanja dugotrajnog poziva. Ne biste trebali postavljati lokalne varijable na nulu, jer ona nije potrebna; runtime može odrediti na koji se lokalni objekt ne navodi referenca u vašem kodu ili se on dalje ne koristi, tako da ne morate lokalnu varijablu eksplicitno postaviti na nulu.