Einführung
Speicherlecks in einer.NET-Anwendung waren schon immer der Albtraum eines Programmierers. Speicherlecks sind das schlimmste Problem bei Produktionsservern. Produktionsserver müssen normalerweise mit der geringsten Ausfallzeit laufen. Speicherlecks wachsen langsam und bringen mit der Zeit den Server zum Absturz, indem sie riesige Speichermengen verbrauchen. Meistens starten die Leute das System neu, lassen es vorübergehend funktionieren und schicken dem Kunden eine Entschuldigung für die Ausfallzeit.
Bitte laden Sie mein kostenloses E-Book mit 500 Fragen und Antworten herunter, das .NET, ASP.NET, SQL Server, WCF, WPF und WWF abdeckt.http://www.questpond.com/.
Vermeiden Sie den Task-Manager, um Speicherverluste zu erkennen
Die erste und wichtigste Aufgabe besteht darin, zu bestätigen, dass ein Speicherverlust vorliegt. Viele Entwickler verwenden den Windows-Task-Manager, um zu überprüfen, ob in der Anwendung ein Speicherverlust vorliegt. Die Verwendung des Task-Managers ist nicht nur irreführend, sondern liefert auch nicht viele Informationen darüber, wo der Speicherverlust liegt.
Versuchen wir zunächst zu verstehen, warum die Speicherinformationen des Task-Managers irreführend sind. Der Task-Manager zeigt den Arbeitsspeicher und nicht den tatsächlich verwendeten Speicher an. Ok, was bedeutet das? Bei diesem Speicher handelt es sich um den zugewiesenen Speicher und nicht um den verwendeten Speicher. Durch weiteres Hinzufügen kann etwas Speicher aus dem Arbeitssatz von anderen Prozessen/Anwendungen gemeinsam genutzt werden.
Daher kann der Arbeitsspeicher größer sein als der tatsächlich genutzte Speicher.
Verwendung von Leistungsindikatoren für private Bytes zur Erkennung von Speicherverlusten
Um die von der Anwendung verbrauchte Speichermenge korrekt zu ermitteln, müssen wir die von der Anwendung verbrauchten privaten Bytes verfolgen. Private Bytes sind Speicherbereiche, die nicht von anderen Anwendungen gemeinsam genutzt werden. Um die von einer Anwendung verbrauchten privaten Bytes zu erkennen, müssen wir Leistungsindikatoren verwenden.
Die Schritte, die wir befolgen müssen, um private Bytes in einer Anwendung mithilfe von Leistungsindikatoren zu verfolgen, sind:
-
Starten Sie Ihre Anwendung, bei der ein Speicherverlust auftritt, und lassen Sie sie laufen.
-
Klicken Sie auf „Start“ und dann auf „Ausführen“ und geben Sie „perfmon“ ein.
-
Löschen Sie alle aktuellen Leistungsindikatoren, indem Sie den Zähler auswählen und ihn durch Klicken auf die Schaltfläche „Löschen“ löschen.
-
Klicken Sie mit der rechten Maustaste, wählen Sie „Zähler hinzufügen“ und wählen Sie „Prozess“ aus dem Leistungsobjekt aus.
-
Wählen Sie aus der Zählerliste „Private Bytes“ aus.
-
Wählen Sie aus der Instanzliste die Anwendung aus, für die Sie den Speicherverlust testen möchten.
Wenn Ihre Anwendung einen stetigen Anstieg des privaten Bytewerts aufweist, bedeutet dies, dass hier ein Speicherverlustproblem vorliegt. In der folgenden Abbildung können Sie sehen, wie der Wert der privaten Bytes stetig zunimmt, was bestätigt, dass in der Anwendung ein Speicherverlust vorliegt.
Die obige Grafik zeigt einen linearen Anstieg, aber in der Live-Implementierung kann es Stunden dauern, bis der Anstieg sichtbar wird. Um einen Speicherverlust zu überprüfen, müssen Sie den Leistungsindikator stunden- oder wahrscheinlich tagelang auf dem Produktionsserver laufen lassen, um zu prüfen, ob tatsächlich ein Speicherverlust vorliegt.
3-stufiger Prozess zur Untersuchung von Speicherlecks
Sobald wir bestätigt haben, dass ein Speicherverlust vorliegt, ist es an der Zeit, das Grundproblem des Speicherverlusts zu untersuchen. Wir werden unseren Weg zur Lösung in drei Phasen unterteilen: Was, Wie und Wo.
-
Was: - Wir werden zunächst versuchen zu untersuchen, um welche Art von Speicherverlust es sich handelt, ob es sich um einen verwalteten Speicherverlust oder einen nicht verwalteten Speicherverlust handelt.
-
Wie: - Was verursacht den Speicherverlust wirklich? Ist es das Verbindungsobjekt, eine Art Datei, deren Handle nicht geschlossen ist usw.?
-
Wobei: – Welche Funktion/Routine oder Logik verursacht den Speicherverlust?
Was ist die Art von Speicherverlust? Gesamtspeicher = verwalteter Speicher + nicht verwalteter Speicher
Bevor wir versuchen, die Art des Lecks zu verstehen, versuchen wir zu verstehen, wie Speicher in .Net-Anwendungen zugewiesen wird. .NET-Anwendungen verfügen über zwei Arten von speicherverwaltetem Speicher und nicht verwaltetem Speicher. Der verwaltete Speicher wird durch die Garbage Collection gesteuert, während sich der nicht verwaltete Speicher außerhalb der Grenzen der Garbage Collectors befindet.
Als Erstes müssen wir also sicherstellen, dass es sich um einen verwalteten Speicherverlust oder einen nicht verwalteten Speicherverlust handelt. Um festzustellen, ob es sich um ein verwaltetes oder ein nicht verwaltetes Leck handelt, müssen wir zwei Leistungsindikatoren messen.
Der erste ist der Zähler für private Bytes für die Anwendung, den wir bereits in der vorherigen Sitzung gesehen haben.
Der zweite Zähler, den wir hinzufügen müssen, ist „Bytes in allen Heaps“. Wählen Sie also „.NET CLR-Speicher“ im Leistungsobjekt aus, wählen Sie aus der Zählerliste „Bytes in allen Heaps“ aus und wählen Sie dann die Anwendung aus, bei der der Speicherverlust auftritt.
Private Bytes sind der gesamte von der Anwendung verbrauchte Speicher. Bytes in allen Heaps sind der vom verwalteten Code verbrauchte Speicher. Die Gleichung sieht also wie in der folgenden Abbildung dargestellt aus.
Nicht verwalteter Speicher + Bytes in allen Heaps = private Bytes. Wenn wir also den nicht verwalteten Speicher herausfinden möchten, können wir immer die Bytes in allen Heaps von den privaten Bytes subtrahieren.
Nun machen wir zwei Aussagen:
-
Wenn die privaten Bytes zunehmen und die Bytes in allen Heaps konstant bleiben, handelt es sich um einen nicht verwalteten Speicherverlust.
-
Wenn die Bytes in allen Heaps linear ansteigen, liegt ein verwalteter Speicherverlust vor.
Unten sehen Sie einen typischen Screenshot eines nicht verwalteten Lecks. Sie können sehen, dass die privaten Bytes zunehmen, während die Bytes in Heaps konstant bleiben
Unten sehen Sie einen typischen Screenshot eines verwalteten Lecks. Die Bytes in allen Heaps nehmen zu.
Wie kommt es zu dem Speicherverlust?
Nachdem wir nun geantwortet haben, welche Art von Speicherverlust auftritt, ist es an der Zeit, zu sehen, wie der Speicherverlust auftritt. Mit anderen Worten: Wer verursacht den Speicherverlust?
Lassen Sie uns also einen nicht verwalteten Speicherverlust injizieren, indem wir die Funktion „Marshal.AllocHGlobal“ aufrufen. Diese Funktion weist nicht verwalteten Speicher zu und verursacht so einen nicht verwalteten Speicherverlust in der Anwendung. Dieser Befehl wird innerhalb des Timers so oft ausgeführt, dass ein großes, nicht verwaltetes Leck entsteht.
- PrivatgeländeLeeretimerUnManaged_Tick(Objektsender,EventArgse)
- {
- Marshal.AllocHGlobal(7000);
- }
Es ist sehr schwierig, ein verwaltetes Leck einzuschleusen, da GC dafür sorgt, dass der Speicher zurückgewonnen wird. Um die Dinge einfach zu halten, simulieren wir einen verwalteten Speicherverlust, indem wir viele Pinselobjekte erstellen und sie einer Liste hinzufügen, die eine Variable auf Klassenebene ist. Es handelt sich um eine Simulation und nicht um ein verwaltetes Leck. Sobald die Anwendung geschlossen wird, wird dieser Speicher wiederhergestellt.
- PrivatgeländeLeeretimerManaged_Tick(Objektsender,EventArgse)
- {
- für(inti=0;i<10000;i++)
- {
- Brushobj=neuSolidBrush(Color.Blue);
- objBrushes.Add(obj);
- }
- }
Wenn Sie wissen möchten, wie Lecks im verwalteten Speicher auftreten können, können Sie sich für weitere Informationen an den schwachen Handler wendenhttp://msdn.microsoft.com/en-us/library/aa970850.aspx.
Der nächste Schritt besteht darin, das Tool „debugdiag“ herunterzuladenhttp://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en
Starten Sie das Debug-Diagnosetool, wählen Sie „Speicher- und Handle-Leck“ und klicken Sie auf „Weiter“.
Wählen Sie den Prozess aus, in dem Sie einen Speicherverlust erkennen möchten.
Wählen Sie abschließend „Regel jetzt aktivieren“.
Lassen Sie nun die Anwendung laufen und das Tool „Debugdiag“ wird im Backend ausgeführt und überwacht Speicherprobleme.
Sobald Sie fertig sind, klicken Sie auf Analyse starten und lassen Sie das Tool die Analyse durchführen.
Sie sollten einen detaillierten HTML-Bericht erhalten, der zeigt, wie nicht verwalteter Speicher zugewiesen wurde. In unserem Code haben wir mithilfe von „AllochGlobal“ riesigen, nicht verwalteten Speicher zugewiesen, was im folgenden Bericht gezeigt wird.
Typ | Beschreibung |
Warnung | mscorlib.ni.dll ist für ausstehende Zuweisungen im Wert von 3,59 MByte verantwortlich. Im Folgenden sind die beiden Funktionen aufgeführt, die am meisten Speicher verbrauchen: System.Runtime.InteropServices.Marshal.AllocHGlobal(IntPtr):Ausstehende Zuweisungen im Wert von 3,59 MByte. |
Warnung | ntdll.dll ist für ausstehende Zuweisungen im Wert von 270,95 KByte verantwortlich. Im Folgenden sind die beiden Funktionen aufgeführt, die am meisten Speicher verbrauchen: ntdll!RtlpDphNormalHeapAllocate+1d: 263,78 KByte ausstehender Zuweisungen. |
Der verwaltete Speicherverlust von Pinseln wird mithilfe von „GdiPlus.dll“ im folgenden HTML-Bericht angezeigt.
Typ | Beschreibung |
Warnung | GdiPlus.dll ist für ausstehende Zuteilungen im Wert von 399,54 KByte verantwortlich. GdiPlus!GpMalloc+16: Ausstehende Zuweisungen im Wert von 399,54 KByte. |
Wo ist der Speicherverlust?
Sobald Sie die Ursache eines Speicherverlusts kennen, ist es an der Zeit herauszufinden, welche Logik den Speicherverlust verursacht. Es gibt kein automatisiertes Tool zum Erkennen der Logik, die Speicherlecks verursacht hat. Sie müssen Ihren Code manuell eingeben und anhand der von „debugdiag“ bereitgestellten Hinweise feststellen, an welchen Stellen die Probleme auftreten.
Aus dem Bericht geht beispielsweise klar hervor, dass „AllocHGlobal“ das nicht verwaltete Leck verursacht, während eines der Objekte von GDI das verwaltete Leck verursacht. Anhand dieser Details müssen wir im Code nachsehen, um herauszufinden, wo genau das Problem liegt.
Quellcode
Sie können den Quellcode oben in diesem Artikel herunterladen, der Ihnen dabei helfen kann, Speicherlecks zu injizieren.
Danke, Danke und Danke
Es wäre von meiner Seite unfair zu sagen, dass der obige Artikel vollständig mein Wissen widerspiegelt. Vielen Dank für all die lieben Menschen, die Artikel geschrieben haben, damit eines Tages jemand wie ich davon profitieren kann.
-
http://blogs.msdn.com/tess/Ein toller Blog der liebenswerten Dame Tess über Debugger. Es gibt einige großartige Labore zur Speicherleckerkennung mit windbg; verpassen Sie sie nicht. Tess, Gott segne dich, dein Blog rockt wie alles andere.
-
http://msdn.microsoft.com/en-us/magazine/cc163491.aspxDies ist ein großartiger Artikel von James Kovacs über verwaltete und nicht verwaltete Speicherlecks, den Sie unbedingt lesen sollten.
-
http://davybrion.com/blog/2009/08/finding-memory-leaks-in-silverlight-with-windbg/Toller Artikel zum Auffinden von Speicherlecks mithilfe von windbg.
-
http://www.itwriting.com/dotnetmem.php:- Toller Link, der den Unterschied zwischen Arbeitssatzspeicher und privaten Bytes ausführlich erklärt.
-
http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=enDownload für das Debugdiag-Tool.
-
http://blogs.msdn.com/davidklinems/archive/2005/11/16/493580.aspxDavid Kline erklärt die drei häufigsten Ursachen für Speicherverluste in verwalteten Anwendungen.
Mein anderer Artikel zu Best Practices für .NET
.NET Best Practice 1: – In diesem Artikel besprechen wir, wie wir Bereiche mit hohem Speicherverbrauch in .NET finden können. Darüber können Sie unter lesenBest Practice für .NET 1
.NET Best Practice 2: – In diesem Artikel besprechen wir, wie wir die Leistung mithilfe des Finalize-/Dispose-Musters verbessern können.Best Practice für .NET 2
.NET Best Practice 3: – Wie können wir Leistungsindikatoren verwenden, um Leistungsdaten von .NET-Anwendungen zu sammeln?Best Practice für .NET 3
.NET Best Practice 4: – Wie können wir die Bandbreitenleistung mithilfe der IIS-Komprimierung verbessern?Best Practice für .NET 4.
FAQs
How to fix resource leak in C#? ›
We can do this by implementing IDisposable. Capturing the local variable instead of the class variable in the anonymous method can avoid a memory leak. Avoiding excessive use of static variables in our application, especially when these variables are of reference types, we can avoid the situation of memory leak.
How do I find a memory leak in .NET code? ›- Set a breakpoint where the class instance is created.
- To open the debugger's data-tip, hover over the variable, then right-click and select Make Object ID. ...
- Complete the scenario that was supposed to de-reference your instance.
- With the known magic lines, force GC collection.
To find memory leaks and inefficient memory usage, you can use tools such as the debugger-integrated Memory Usage diagnostic tool or tools in the Performance Profiler such as the . NET Object Allocation tool and the post-mortem Memory Usage tool.
How to check memory leak in C# net? ›- Start with some kind of Idle state in your application. ...
- Take a snapshot with the Memory profiler by attaching-to-process or saving a Dump .
- Run an operation where you suspect a memory leak is created. ...
- Take a second snapshot.
- Compare both snapshots with your memory profiler.
Close the Problematic App & Restart Your Computer
The best way to fix memory leaks in Windows is by closing the program and processes that are eating up the most memory. Press CTRL + Shift + Esc key together to launch Task Manager. Click on the Processes and find the program using most memory from the list.
- Implement Dispose using 'SafeHandle' Class (It is inbuilt abstract class which has 'CriticalFinalizerObject' and 'IDisposable' interface has been implemented)
- Object. Finalize method to be override (This method is clean unmanaged resources used by particular object before it is destroyed)
It occupies a chunk of memory or continues to gobble up more memory without letting go. Often the program continues to grab memory as the computer slowly grinds to a halt. One way to find a memory leak is to use the Resource Monitor utility. Press the Windows + r keyboard shortcut and type resmon for Resource Monitor.
What causes a memory leak in code? ›The main cause of memory leaks is the negligence of the programmer. Generally, programmers tend to forget to deallocate memory using the delete function and use the new operator and there occurs a wastage of memory, which in turn causes memory leakage in the programming code.
How to check memory leak in SQL? ›You can also get these parameters from task manager - go into the process view, choose view columns and add the relevant columns. If no processes in task manager/perfmon show a memory leak, but the overall memory is still going up, then the leak must be down at the kernel level.
What tool is most commonly used to detect memory leaks? ›Visual VM is a very useful tool for developers to trace and track memory leaks. It analyzes heap data and garbage collectors. It ensures the optimized use of memory and helps to improve the application performance.
How to clear unmanaged memory in C#? ›
To clear all the unmanaged resources held by a class, we need to inherit that class from the IDisposable interface and implement the Dispose method. We have to write all the cleanup code in DisposeMethod. Whenever we want to free the resources held by the object, we can call the Dispose method.
Does memory leak occur when you forget to free memory? ›A memory leak occurs when you have dynamically allocated memory, using malloc() or calloc() that you do not free properly. As a result, this memory is lost and can never be freed, and thus a memory leak occurs.
Can .NET have memory leak? ›While the . Net Common Language Runtime (CLR) abstracts away memory management from developers, memory leaks are still possible. This programming tutorial talks about memory leaks, why they occur, and the best practices that can be followed to avoid them in ASP.NET applications.
How do I find memory leaks in Visual VM? ›With Java VisualVM, we can memory-monitor the Java Heap and identify if its behavior is indicative of a memory leak. After just 30 seconds, the Old Generation is almost full, indicating that, even with a Full GC, the Old Generation is ever-growing, a clear sign of a memory leak.
How to find memory leak with VisualVM? ›Attach VisualVM to your application. Perform the operation that causes the sluggish performance. Inspect the 'Monitor' and the 'memory pools' tab. If you see that your memory increases in the 'Monitor' tab, try pressing 'Perform GC' (garbage collection) and see if that decreases memory usage.
How to change the resource file in C#? ›- Right click the 'Default.aspx.resx' file and click the Copy.
- Right click the App_LocalResources folder and click the Paste.
- Right click the 'Copy of Default.aspx.resx' and click the Rename.
- Type the new name for the resource file that includes the new language and culture code before the extension.
A memory leak occurs when a programmer does not allocate a previously allocated memory, resulting in deallocation, which thus causes a memory leak. This is because the program does not require this memory but it is still present in the program.
What is a memory leak in C# and the .NET framework? ›A memory leak may happen when your app references objects that it no longer needs to perform the desired task. Referencing said objects prevents the garbage collector from reclaiming the memory used, often resulting in performance degradation and potentially ending up throwing an OutOfMemoryException.