Memory Leak finden - Instanzen anzeigen im Debugger

  • VB.NET
  • .NET (FX) 4.0

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

    Memory Leak finden - Instanzen anzeigen im Debugger

    Ich habe ein relativ komplexes Programm, das permanent neue Instanzen eigener und fremder Klassen erzeugt (und nach Gebrauch auch wieder freigibt).

    Leider steigt der Speicherverbrauch ständig an und ich suche jetzt das Memory Leak.
    Gibt es eine Möglichkeit im Debugger (oder anderweitig) anzuzeigen, welche Klassen momentan wie viele Instanzen haben?

    Ich verwende Visual Studio 2015 Professional.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    @petaod Fang an mit einer Code-Analyse.
    Ich hab zwar nur das 13er Studio, aber das müsste im 15er genau so sein.
    Projekt-Eigenschaften-Codeanalyse
    Auswahl auf All Microsoft Rules
    Nicht aktivieren (sonst wird das bei jedem Buiold gemacht)
    und dann im Menü Erstellen -> Codeanalyse durchführen.
    Da musst Du erst mal ein Gefühl für den Output kriegen, aber das wichtigste ist, dass er anzeigt, wo IDisposable-Instanzen nicht disposed wurden.
    Die räumst Du alle auf und siehst weiter. :thumbup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das war schon mal ein guter Ansatz.
    Damit habe ich ein paar Bagatellen ausgebügelt, wo nicht sauber disposed wurde.

    Der große Wurf ist aber damit noch nicht gelungen.
    Ich hab's jedoch mittels den Diagnosetools im Visual Studio und gezielten Breakpoints ein wenig eingekreist.
    Die großen Leaks entstehen innerhalb der eingebundenen SSH.Net Library im Sftp.Client.
    Ich schau mal, was da machbar ist.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Hi
    ist das ein renommiertes Projekt? Ich habe gesehen, dass die BigInteger im Diffie-Hellman zu verwenden scheinen, das wäre eine Schwachstelle, da da die Berechnungen unterschiedlich lange dauern. Ich bin aber kein Sicherheitsexperte. Ich würde nur Sachen verwenden, die sich über die Jahre einen Namen gemacht haben, da die idR. sicher sind - mal von heartbleed abgesehen...

    Viele Grüße
    ~blaze~

    petaod schrieb:

    SSH.Net Library
    Hatte ich noch nix mit zu tun.
    Kannst Du mal kurz beschreiben, was die macht?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    SSH.Net ist eine Secure Shell Bibliothek für .Net.
    Die hat Client- und Server-Methoden für SSH, SCP, SFTP und alle möglichen anderen verschlüsselte Verbindungen.
    Ich benutze hier den SFTP-Client.

    Nachdem ich nun weiss, dass die Leaks in dieser Bibliothek erzeugt werden, habe ich in dieser Richtung etwas recherchiert.
    Einen Teil der Leaks konnte ich wegbringen, indem ich die Events nicht abonniere, also das WithEvents beim instantiieren nicht verwende.
    Dennoch läuft das Memory bei jedem Download etwas hoch.
    Ich verwende dafür SftpClient.ReadAllBytes.

    Im Normalbetrieb wird das wohl einige Tage halten, bevor es zu echten Problemen kommt.
    Allerdings wenn mal ein paar tausend Dateien geladen wurden, wird's eng.
    Ich fürchte, da muss ich mir einen regelmässigen Reset einfallen lassen.

    ~blaze~ schrieb:

    ist das ein renommiertes Projekt?
    Nicht wirklich.
    Die Daten auf dem Server sind mehr oder weniger auch öffentlich erhältlich.
    Nur sind sie auf dem SFTP-Server sofort nach Veröffentlichung verfügbar und tragen einen Timestamp, während man für andere Kanäle einen Webserver pollen müsste und erst mal rauskriegen muss, ob es neue Daten gibt.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „petaod“ ()

    @petaod Wir hatten mal ein Problem mit einer gekauften Bildverarbeitung, da musste gelegentlich GC.Collect() aufgerufen werden.
    Vielleicht hilft das bei Dir auch.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    GC.Collect()
    werde ich morgen mal versuchen.
    Momentan lass ich einen Stresstest laufen und es sieht so aus, dass tatsächlich das Weglassen von WithEvents erst mal ausreicht.
    Die Auslastung geht zwar immer wieder etwas hoch, aber der GC scheint das mit Zeitversatz regelmässig aufzuräumen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Welche Methoden von SftpClient rufst du denn auf? Nur ReadAllBytes?

    Hast du übrigens gesehen, dass es eine neuere Version davon zu geben scheint?
    So vom drüberschauen halte ich irgendwie immer weniger von der Library, so vom drüberlesen. In SftpSession hab' ich einige Dinge gesehen, die so nicht funktionieren dürften (z.B. ein Timeout sollte eine ObjectDisposedException werfen). Außerdem findet sich ziemlich viel redundanter Code darin wieder.

    Also falls du was besseres findest, würde ich ggf. darauf ausweichen.

    Der GC sollte eigentlich sowieso immer mal wieder aufräumen, ich weiß nicht, ob es wirklich daran liegen kann.

    Beim durchlesen des Codes hätte ich gesagt, dass das Problem irgendwo in Session oder deren Abhängigkeiten festzumachen ist. Hatte jetzt keine Lust mehr, weiter durchzugehen.
    Im Auge hatte ich besonders die SendMessage-Methode bzw. die darin aufgerufene _clientCompression.Compress. Ich hab den restlichen Code nur überflogen, aber sonst keine wirklich kritischen Passagen gefunden.

    Viele Grüße
    ~blaze~

    ~blaze~ schrieb:

    Welche Methoden von SftpClient rufst du denn auf?
    GetLastWriteTimeUtc für den Folder (ob es überhaupt eine Veränderung gab) und ListDirectory, um die neuen Dateien zu finden.
    Aber beide Methoden scheinen harmlos zu sein.
    Kritisch ist wirklich nur ReadAllBytes.

    Falls jemand eine gute .Net-Bibliothek für einen SFTP-Client kennt, kann ich auch gerne was anderes testen.
    Die SSH.Net hatte halt bei nuget die mit Abstand meisten Downloads und das hat mich dazu bewogen, die zu verwenden.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Würde wohl dafür sprechen, dass es nichts besseres gibt... Ich hätte jetzt auf die Schnelle auch nichts anderes gefunden.

    Wenn es dir nicht auf Sicherheit ankommt, passt das aber, denke ich. Damit werben, dass es SSH-Unterstützung hat, würde ich aber nicht unbedingt... ;)

    Ich denke, dass GetLastWriteTimeUtc und ListDirectory beides nur Kommandos sind und die auf die gleichen Methoden zurückgreifen, wie ReadAllBytes.
    Geh' mal in den Diagnosetools auf Speicherauslastung und dort auf Momentaufnahme. Wähle dann den Link bei Heapgröße oder Objekte aus und du solltest eine Übersicht darüber erhalten. Dort solltest du feststellen können, was anwächst.

    Viele Grüße
    ~blaze~

    ~blaze~ schrieb:

    Wähle dann den Link bei Heapgröße oder Objekte aus und du solltest eine Übersicht darüber erhalten
    Genau das habe ich gesucht!
    Super. Vielen Dank.

    Ich warte jetzt mal bis mein Lasttest durch ist und werde dann damit ein paar Traces machen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --