Hvilke strategier og verktøy er nyttige for å finne minnelekkasjer i .NET?

 C Programming >> C C# Program >  >> Tags >> .NET
Hvilke strategier og verktøy er nyttige for å finne minnelekkasjer i .NET?

Jeg bruker Scitechs MemProfiler når jeg mistenker en minnelekkasje.

Så langt har jeg funnet det veldig pålitelig og kraftig. Det har reddet baconet mitt ved minst én anledning.

GC fungerer veldig bra i .NET IMO, men akkurat som alle andre språk eller plattformer, hvis du skriver dårlig kode, skjer dårlige ting.


Bare for å glemme-å-kassere-problemet, prøv løsningen beskrevet i dette blogginnlegget. Her er essensen:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

Vi har brukt Ants Profiler Pro av Red Gate-programvare i prosjektet vårt. Det fungerer veldig bra for alle .NET språkbaserte applikasjoner.

Vi fant ut at .NET Garbage Collector er veldig "trygg" når det gjelder å rydde opp i minneobjekter (som den burde være). Det ville holde gjenstander rundt bare fordi vi kan skal bruke den en gang i fremtiden. Dette betydde at vi måtte være mer forsiktige med antall gjenstander vi blåste opp i minnet. Til slutt konverterte vi alle dataobjektene våre til en "oppblåsing på forespørsel" (rett før et felt blir forespurt) for å redusere minnekostnader og øke ytelsen.

EDIT:Her er en ytterligere forklaring på hva jeg mener med "blås opp etter behov." I vår objektmodell av databasen vår bruker vi Egenskaper til et overordnet objekt for å eksponere underobjektet(e). Hvis vi for eksempel hadde en post som refererte til en annen "detalj" eller "oppslag"-post på en-til-en-basis, ville vi strukturert den slik:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

Vi fant ut at systemet ovenfor skapte noen reelle minne- og ytelsesproblemer da det var mange poster i minnet. Så vi byttet over til et system der objekter bare ble oppblåst når de ble forespurt, og databaseanrop bare ble utført når det var nødvendig:

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

Dette viste seg å være mye mer effektivt fordi objekter ble holdt utenfor minnet til de var nødvendige (Get-metoden ble åpnet). Det ga en veldig stor ytelsesøkning i å begrense databasetreff og en enorm gevinst på minneplass.