Ich habe eine Klasse, die für das Herunterladen von Dateien in einem Download-Manager zuständig ist. Diese Klasse ist verantwortlich für das Herunterladen der Datei und das Schreiben in den angegebenen Pfad.
Die Größe der herunterzuladenden Dateien variiert normalerweise von 1 bis 5 MB, könnte aber auch viel größer sein. Ich verwende eine Instanz der WebClient-Klasse, um die Datei aus dem Internet zu erhalten.
%Vor%Jeder Download verursacht einen sehr großen Speicheranstieg im Vergleich zur Dateigröße des heruntergeladenen Elements. Wenn ich eine Datei mit einer Größe von ~ 3 MB herunterlade, erhöht sich die Speicherbelegung um ca. 8 MB.
Wie Sie sehen, erzeugt der Download viel LOH, das nach dem Download nicht gelöscht wird. Das Erzwingen des GC oder der Einstellung GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
trägt nicht dazu bei, diesen Speicherverlust zu verhindern.
Beim Vergleich von Snapshot 1 und 2 können Sie sehen, dass die Menge an Speicher von Byte-Arrays erzeugt wird, die das Download-Ergebnis sein können.
Das Ausführen mehrerer Downloads zeigt, wie schrecklich dieses Speicherleck ist.
Meiner Meinung nach wird dies durch die WebClient-Instanz in irgendeiner Weise verursacht. Ich kann jedoch nicht wirklich feststellen, was genau dieses Problem verursacht. Es ist nicht einmal wichtig, ob ich den GC erzwinge. Dieser Bildschirm zeigt es ohne erzwungenes GC:
Was verursacht diese Überhitzung und wie kann ich sie beheben? Dies ist ein schwerwiegender Fehler und wenn man sich 100 oder mehr Downloads vorstellt, würde der Prozess keinen Speicher mehr haben.
Bearbeiten
Wie vorgeschlagen, habe ich den Abschnitt, der für das Setzen der Tags und das Umwandeln des M4A in MP3 zuständig ist, auskommentiert. Der Konverter ist jedoch nur ein Aufruf von FFMPEG, also sollte es kein Speicherleck sein:
%Vor% Die Methode DownloadCompleted()
sieht nun so aus:
Das Ergebnis nach dem Herunterladen von 7 Artikeln: Es scheint, als wäre das nicht das Speicherleck.
Als Ergänzung übergebe ich auch die DownloadManager
-Klasse, da sie den gesamten Downloadvorgang behandelt. Vielleicht könnte dies die Ursache des Problems sein.
Nach Dutzenden von Profiling- und Speicherüberprüfungen ist das Problem nun behoben.
Wie @SimonMourier bereits festgestellt hat, hängt dieses Problem mit dem Design der Methoden UploadFile
, DownloadData
, DownloadString
und DownloadFile
zusammen. Wenn Sie in das Backend schauen, sehen Sie, dass alle die private DownloadBits
-Methode in der Klasse WebClient
mit dieser Signatur verwenden:
In Bezug auf den Rückgabetyp ist klar, warum das Verhalten so ist, wie ich es entdeckt habe: Bei Verwendung der oben genannten Methoden wird der Inhalt in einem Byte-Array gespeichert. Daher wird es nicht empfohlen, diese Methoden zu verwenden, wenn die Dateigröße & gt; 85.000 Bytes, da dies zum Füllen des LOH führen würde, bis das Speicherlimit erreicht ist. Dies ist möglicherweise nicht wichtig, wenn die Dateien klein sind, aber mit wachsender Größe wächst auch die LOH um ein Vielfaches.
Als Ergänzung hier meine endgültige Lösung:
%Vor%Aber danke für die Hilfe!
Tags und Links memory-leaks memory c# garbage-collection webclient