210 likes | 587 Views
Memory Leaks i .Net Av Jon Arild Tørresdal Definisjon “a memory leak is a particular kind of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed.” Wikipedia Agenda Garbage collector Hvor mye minne bruker min app?
E N D
Memory Leaks i .Net Av Jon Arild Tørresdal
Definisjon “a memory leak is a particular kind of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed.” Wikipedia
Agenda • Garbage collector • Hvor mye minne bruker min app? • Eksempler på minnelekasjer • Hvordan finne minnelekasjer • Finalize(~) • Dispose pattern • Using direktivet • Konklusjon
Garbage Collector • Ansvarlig for å finne ”løse” objekter. Dvs objekter som ikke lenger har noen referenter og fjerne disse. • GC jobber på heap’en, hvor alle objekter ligger. • Heap’en er delt inn i 3 generasjoner. • Hver gang det kjøres garbage collection og et objekt overlever, flyttes det til neste generasjon. • Det finnes også en large heap, som inneholder objekter større enn 20mb. • GC er optimert for minne håndtering og bør ikke kalles manuelt (GC.Collect). Den gjør en god jobb!
Hvor mye minne bruker min app? Mulig verktøy: • Task manager • PerfMon (Perfomance Monitor) • System.Diagnostics.Process • GC.GetTotalMemory(true/false)
Task manager • De aller fleste ser på kolonnen Mem Usage. • MemUsage (working set) sier noe om: • Hvor mye RAM som på et gitt tidspunkt er dedikert til en gitt prosess. • MemUsage sier ikke noe om: • Hvor mye minne applikasjonen din bruker!
Task manager • VMSize derimot, sier noe om: • Hvor mange private bytes som applikasjonen benytter. • Private bytes er hvor mye som er brukt (commited) av virtuelt minne • Ved å følge med på VMSize i applikasjonen din kan du få en indikasjon på minne lekasjer (minnet øker og øker) • I Vista er det nettopp VMSize (private memory) som vises i TaskManager’en
PerfMon • Inneholder mange tellere (counters) for blant annet minne bruk. • Mest interesant er Process->Private Bytes og Process->Virtual Bytes • Private Bytes er det samme som VMSize i TaskManager • Virtual Bytes sier noe om størrelsen på reservert og brukt minne.
System.Diagnostics.Process • PrivateMemorySize • VirtualMemorySize • WorkingSet • Flere... • Disse er de samme som nevt tidligere, bare tilgjengelig i kode.
GC.GetTotalMemory • I MSDN dokumentasjonen står følgende: • A number that is the best available approximation of the number of bytes currently allocated in managed memory
Hvordan oppdage/finne minnelekasjer Verktøy • TaskManager • Memory Profiler • Ants Profiler • Andre...
Minnelekasjer i kode • Demo
Finalize • ~ i c# • Finalize i VB • Blir kalt av GC hvis objektet ikke har referenter og objekter er merket finalizable • Brukt til å fjerne eventuell gjenværende resurser. Typisk unmanaged objekter.
Demo • Debug finalize
Hva er galt med Finalize? • Et object som har Finalize bruker lengre tid på å initialisere • Bruker lengre tid på å forsvinne fra heap’en • Hvis GC finner et object som det må kjøres finalize på, legges objectet i neste generasjon klar for finalize. • Det vil da si at objektet ikke forsvinner fra heap’en før GC kjører collect på den generasjonen.
Hva er galt med Finalize? • Oppretter objekt • GC kjøres i Gen0 • Objekt overlever og blir flyttet til Gen1 • Objektet er klar for å fjernes • GC kjøres i Gen1 • Objectet er Finalizable, så det flyttes til Gen2 • Etter lang tid kjører GC i Gen2 • Objectet forsvinner fra heap’en
IDisposable og Dispose • Et pattern som er fullt støttet i .Net • Til for å hjelpe/erstatte finalize • I motsetning til Finalize(~) blir ikke Dispose kalt automatisk, det er din oppgave!!! • Finalize bør(må) kalle Dispose(false) • Dispose bør(må) kalle SupressFinalize • Dispose hjelper til med performance og hindrer minne lekasjer
Bruk av Using • I stedet for å kalle Dispose, kan en bruke Using direktivet using(disposableObject obj = new disposableObject()) { //Do stuff with disposableObject. } • På denne måten blir Dispose kalt automagisk.
Konklusjon • Det er fullt mulig og vanlig å få minne lekasjer i .Net. • Til større applikasjon, desto større mulighet for minnelekasjer. • Vær obs på at 3. parts komponenter også kan ha minne lekasjer! • Husk alltid å kalle Dispose på objekter som har Dispose!!!!!!!!!! • Events er en stor synder til minne lekasjer • Invister i verktøy som MemProfiler eller Ants Profiler. • Hvis du tror at nettopp din applikasjon ikke har minne lekasje, så tar du mest sansynlig feil