156 votes

Quelles stratégies et quels outils sont utiles pour rechercher des fuites de mémoire dans .NET?

J'ai écrit en C++ pour 10 ans. J'ai rencontré des problèmes de mémoire, mais ils pourraient être fixés avec une quantité raisonnable de l'effort.

Pour les deux dernières années, j'ai écrit en C#. Je trouve que je reçois encore beaucoup de problèmes de mémoire. Elles sont difficiles à diagnostiquer et à résoudre en raison de la non-determinancy, et parce que le C# philosophie est que vous ne devriez pas avoir à vous soucier de ces choses quand vous avez très certainement le faire.

Un problème particulier je trouve, c'est que j'ai explicitement disposer de nettoyage et de tout ce qui dans le code. Si je ne le fais pas, les profileurs de mémoire n'ont pas vraiment aider, car il y a beaucoup de pellicules, flottant sur vous ne pouvez pas trouver une fuite au sein de toutes les données qu'ils essaient de vous le montrer. Je me demande si j'ai eu la mauvaise idée, ou si l'outil que j'ai reçu n'est pas le meilleur.

Ce genre de stratégies et d'outils sont utiles pour lutter contre les fuites de mémoire .NET?

53voto

GEOCHET Points 13787

J'utilise MemProfiler de Scitech lorsque je soupçonne une fuite de mémoire.

Jusqu'à présent, je l'ai trouvé très fiable et puissant. Cela m'a sauvé le bacon au moins une fois.

Le GC fonctionne très bien dans .NET IMO, mais comme dans tout autre langage ou plate-forme, si vous écrivez un code incorrect, de mauvaises choses se produisent.

41voto

Jay Bazuzi Points 20462

Juste pour le problème de l’oubli, essayez la solution décrite dans cet article de blog . Voici l'essentiel:

     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
 

17voto

Mark Points 186

Nous avons utilisé les Fourmis Profiler Pro en logiciel de Porte Rouge dans notre projet. Cela fonctionne vraiment bien pour tous .NET de la langue en fonction des applications.

Nous avons constaté que les .NET Garbage Collector est très "safe" dans son le nettoyage des objets en mémoire (comme il faut). Il serait de garder les objets autour juste parce que nous avons peut - être l'utiliser dans le futur. Cela signifiait que nous devions être plus prudent sur le nombre d'objets que nous avons gonflé dans la mémoire. En fin de compte, nous avons converti l'ensemble de nos objets de données de plus de à un "gonfler à la demande" (juste avant un champ est demandé) afin de réduire la surcharge de la mémoire et améliorer les performances.

EDIT: Voici une explication plus détaillée de ce que je veux dire par "gonfler à la demande." Dans notre modèle d'objet de notre base de données nous utilisons les Propriétés d'un objet parent pour exposer l'objet enfant(s). Par exemple, si nous avons eu quelques record qui faisait référence à un autre "détail" ou "recherche" enregistrement sur un un-à-un, nous permettrait de structure comme ceci:

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

Nous avons constaté que le système ci-dessus créé certains réel de la mémoire et des problèmes de performances lorsque il y avait un grand nombre d'enregistrements dans la mémoire. Nous avons donc opté pour un système où les objets étaient gonflés que lorsqu'elles ont été demandées, et de la base de données des appels ont été effectués uniquement lorsque c'est nécessaire:

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

Ceci s'est avéré être beaucoup plus efficace parce que les objets étaient conservés hors de la mémoire jusqu'à ce qu'ils ont besoin (la méthode Get a été consulté). Il a fourni un très gros gain de performances dans la limitation de la base de données de frappe et un énorme gain d'espace mémoire.

9voto

Brian ONeil Points 3012

J'ai trouvé quelques vraiment bons articles qui ont été utile pour moi quand on regarde les problèmes de mémoire .NET et j'ai gardé une référence pour eux donc je les avoir autour.

Débogage des Problèmes de Mémoire (MSDN)

Les Outils de débogage pour Windows

SOS Débogage Extensions

Ils ont tous été très utile. Je viens d'une C++ arrière-plan, trop donc je sais ce que tu veux dire. À la fin, il y a beaucoup de chevauchement dans les outils que vous utilisez pour regarder ces problèmes. Espérons que cette aide.

7voto

John Miller Points 499

Vous voudrez peut-être consulter dotTrace de JetBrains (fabricants de Resharper). Outil fantastique!

http://www.jetbrains.com/profiler/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X