Bästa metoder för att underlätta skräpsamling i .Net

I Microsoft.Net är skräpsamling en mekanism som antagits av Common Language Runtime (CLR) för att rensa upp de resurser som konsumeras av din applikation. När du skapar objekt i .Net lagras de i den hanterade högen. Medan du behöver skapa objekt behöver du i de flesta fall inte vara orolig för att städa upp objekten - körtiden skulle göra det åt dig.

Du bör dock använda bästa praxis i din ansökan för att underlätta skräpsamlingen och hjälpa den att städa upp resurserna snabbare. Även om .Net är skickliga på att återvinna hanterade objekt, bör du följa vissa riktlinjer för att underlätta snabbare skräpsamling för att förbättra prestandan för din applikation. I den här artikeln vill jag presentera en diskussion om hur skräpsamling fungerar och de bästa metoderna för att underlätta skräpsamlingen i .Net.

När sker skräpuppsamling?

Sopuppsamling sker när systemet har lågt tillgängligt fysiskt minne eller GC.Collect()metoden kallas uttryckligen i programmets kod. Objekt som inte längre används eller som inte kan nås från roten är kandidater för skräpsamling. I huvudsak rensar sopuppsamlaren minnet som upptas av föremål som inte har några referenser.

Generationer

Runtiden organiserar den hanterade högen i generationer. Den använder dessa generationer för att organisera kort- och långlivade objekt. Det bör noteras att sopuppsamlaren arbetar mycket oftare i de lägre generationerna än i de högre. Generation 0 innehåller kortlivade objekt som tillfälliga objekt. När ett objekt skapas lagras det i generation 0 såvida det inte är ett stort objekt. Om föremålet är ett stort objekt lagras det i stora objekthög (LOH) i Generation 2. I de flesta fall återvinns Generation 0-objekten av sopuppsamlaren när det går i bakgrunden.

När du skriver kod bör du följa vissa bästa metoder. Som ett exempel bör du skapa objekt i det lokala omfånget så mycket som möjligt för att underlätta skräpsamlingen. Objekt som skapas i det högre omfånget finns i allmänhet i minnet under en längre tidsperiod. Du kan dra nytta av CLR-profilen för att förstå fördelningsmönstren för din applikation.

Du bör undvika att anropa GC.Collect()metoden eftersom den orsakar en fullständig samling av alla generationer (Generation 0, 1 och 2). När du ringer till GC.Collect()metoden besöker runtime alla liveobjekt i din applikation. Detta tar mycket tid och är följaktligen en mycket dyr operation. Som ett resultat är det inte bra att anropa GC.Collect()metoden.

Om du måste anropa GC.Collect()metoden bör du ringa GC.WaitForPendingFinalizers()efter samtalet för GC.Collect()att säkerställa att den aktuella körtråden väntar tills slutförare för alla objekt har körts.

Därefter ska du ringa GC.Collect()metoden igen för att se till att du samlar in de döda föremål som finns kvar. Dessa döda objekt som kan ha skapats på grund av anropet till finaliseringsmetoden på objekten. Följande kodavsnitt visar hur dessa metoder används.

System.GC.Collect();

System.GC.WaitForPendingFinalizers();

System.GC.Collect();

Du bör se till att du minimerar dolda tilldelningar och skriver din kod på ett sådant sätt att chanserna för marknadsföring av kortlivade objekt till högre generationer elimineras. Du bör inte referera till kortlivade objekt från de långlivade för att undvika marknadsföring av kortlivade objekt till högre generationer.

Du bör också undvika att skriva finaliserare för dina klasser. Om du har en finaliserare implementerad i din klass skulle objekt av sådana klasser bli objekt med lång livslängd eftersom körtiden behöver främja de slutliga objekten till äldre generationer. Du bör ställa in objekt till null innan du ringer ett långvarigt samtal om sådana objekt inte behövs av applikationen. Om du inte längre behöver ett statiskt objekt eller andra objekt i din applikation, bör du ställa in det på null innan du ringer ett långvarigt samtal. Du bör inte ställa in lokala variabler till null eftersom de inte behövs. runtime kan avgöra vilket lokalt objekt som inte refereras till i din kod eller inte används längre, så du behöver inte ställa in någon lokal variabel till null uttryckligen.