Ich habe eine c # -Anwendung, die von einer unmanaged Assembly eines Drittanbieters abhängt, um auf bestimmte Hardware zuzugreifen.
Der nicht verwaltete Code weist einen Speicherverlust auf, der den Speicherverbrauch nach jedem Zugriff um ca. 10 MB erhöht. Das Problem ist bekannt; Es ist kein Bugfix verfügbar.
Gibt es eine Möglichkeit, diese Assembly weiterhin ohne regelmäßige Neustarts zu verwenden?
Ich habe versucht, eine separate AppDomain zu erstellen, den anstößigen Code über appDomain.CreateInstanceAndUnwrap()
in die AppDomain zu laden und dann die Domain später über AppDomain.Unload()
zu entladen. Dies befreit jedoch nicht den nicht verwalteten Speicher, der von dieser Domäne verwendet wird, nur den verwalteten Speicher.
Ich könnte die Anwendung auch in zwei unabhängige Teile aufteilen und nur den Teil mit der nicht verwalteten DLL neu starten. Dies würde jedoch eine große Neukonstruktion bedeuten und wahrscheinlich eine starke Verlangsamung verursachen, da große Datenmengen zwischen diesen beiden Teilen ausgetauscht werden müssten.
Gibt es eine andere Möglichkeit, diese undichte Baugruppe zu zähmen und zu zwingen, ihren Speicher ohne Neustart freizugeben?
Wie Sie es beschreiben, weist die DLL nicht verwalteten Speicher zu. Diese Art von Speicher wird vom Entladen einer App-Domain leider nicht beeinflusst, wie Sie bereits herausgefunden haben.
Sie haben ein paar Optionen, aber ich denke nicht, dass einige von ihnen ansprechend sind:
Es könnte eine fünfte oder eine sechste Option geben, aber denken Sie, die obigen 4 decken die Dinge ab, die mir von meinem Kopf gekommen sind.
Über die Isolierung in einen separaten Prozess, hier ist, was ich zuerst versuchen würde:
Ich würde einen Prozess hochfahren und Anfragen an ihn senden, indem ich den schnellsten Intra-Prozess-Kommunikationskanal verwende, den Sie finden können. Pipes scheint gut zu passen, oder Speicher-Mapped-Dateien.
Sie würden dann, in diesem separaten Prozess, die Out-of-Memory-Bedingung, hoffentlich ein bisschen früh, erkennen, so dass Sie dem Hauptprogramm mitteilen könnten, dass es darüber nachdenken sollte, einen Ersatzprozess zu starten.
Der Hauptprozess könnte das dann tun, aber anstatt darauf zu warten, dass dieser andere Prozess vollständig in Gang kommt, könnte er noch ein paar mehr Anfragen an die bald tot werdende Instanz pumpen und es ein bisschen mehr füllen, bevor Sie zu der neuen Instanz wechseln und das alte zum Beenden auffordern.
Dies würde die Ausfallzeit auf Kosten der zeitweiligen Bereitstellung eines zusätzlichen Prozesses während der Übergänge minimieren.
All dies hängt sehr von den tatsächlichen Szenarien ab, die Sie haben. Wenn Sie diese DLL 100 oder 1000 Mal pro Sekunde aufrufen müssen, ist in jedem Fall eine Kommunikation zwischen den Prozessen nicht möglich.
Die DLL weist in Ihrem Prozess nicht verwalteten Speicher zu und gibt sie nicht frei. Das Entladen der Anwendungsdomäne wird in diesem Fall offensichtlich nicht hilfreich sein, da der Speicher innerhalb des Prozesses und nicht innerhalb der Anwendungsdomäne zugewiesen wird.
Um das Speicherleck zu beseitigen, müssen Sie den unfreien Speicher freigeben und es gibt zwei Möglichkeiten, dies zu tun: Beenden Sie den Prozess und lassen Sie das Betriebssystem es tun oder befreien Sie es selbst. Um es selbst zu befreien, müssen Sie den Zugriff auf den Speicher erhalten, indem Sie entweder über die öffentliche Schnittstelle der DLL, durch private Implementierungsdetails der DLL oder durch Überprüfen des Heap des Prozesses erhalten. Es ist wahrscheinlich machbar, aber ich denke, es wird weder Spaß machen, noch einfach und vielleicht nicht einmal robust.
Im Vergleich dazu scheint die Lösung mit zwei Prozessen und dem regelmäßigen Neustart des Lecks einfach und robust zu sein. Ich wäre nicht besorgt über die Leistung, weil Sie zum Beispiel Memory-Mapped-Dateien verwenden können Daten und vermeiden Sie es herum kopieren.
Die einfachste Lösung wäre natürlich, das Speicherleck zu reparieren oder es sogar selbst zu reparieren, indem Sie entweder die Quelle reparieren oder die DLL patchen.
Tags und Links memory-leaks c# memory-management unmanaged appdomain