Freigeben über


Messen der Speicherauslastung in Visual Studio (C#, Visual Basic, C++, F#)

Suchen Sie Speicherverluste und ineffizienten Arbeitsspeicher, während Sie mit dem debuggerintegrierten Speicherauslastung-Diagnosetool debuggen. Mit dem Speicherauslastungstool können Sie einen oder mehrere Momentaufnahmen des verwalteten und nativen Momentaufnahme-Heaps erstellen, um ein besseres Verständnis darüber zu erlangen, welchen Einfluss die Speicherauslastung von Objekttypen hat. Sie können die Speichernutzung auch ohne angefügten Debugger analysieren oder auf eine ausgeführte App abzielen. Weitere Informationen finden Sie unter Ausführen von Profilerstellungstools für Release- oder Debugbuilds. Informationen zum Auswählen des besten Speicheranalysetools für Ihre Anforderungen finden Sie unter Auswählen eines Speicheranalysetools.

Obwohl Sie im Tool Speicherauslastung Jederzeit Speichermomentaufnahmen erfassen können, können Sie den Visual Studio-Debugger verwenden, um zu steuern, wie Ihre Anwendung ausgeführt wird, während Leistungsprobleme untersucht werden. Festlegen von Haltepunkten, schrittweises Ausführen, alles unterbrechen und andere Debugger-Aktionen können Ihnen helfen, Ihre Leistungsuntersuchungen auf die relevantesten Codepfade zu fokussieren. Das Ausführen dieser Aktionen während der Ausführung der App kann das Rauschen aus dem Code beseitigen, der Sie nicht interessiert, und die Zeit, die Sie zum Diagnostizieren eines Problems benötigt, erheblich reduzieren.

Wichtig

Die debuggerintegrativen Diagnosetools werden für die .NET-Entwicklung in Visual Studio unterstützt, einschließlich ASP.NET, ASP.NET Core, native/C++-Entwicklung und Mixed Mode-Apps (.NET und systemeigene Apps).

In diesem Tutorial werden Sie folgendes tun:

  • Momentaufnahmen des Arbeitsspeichers erstellen
  • Analysieren von Speichernutzungsdaten

Wenn Speicherauslastung Ihnen nicht die benötigten Daten liefert, stellen andere Profilerstellungstools im Performance Profiler verschiedene Arten von Informationen bereit, die Ihnen möglicherweise hilfreich sind. In vielen Fällen kann der Leistungsengpass Ihrer Anwendung durch etwas anderes als Ihren Speicher verursacht werden, z. B. die CPU, das UI-Rendering oder die Netzwerkanfragenzeit.

Anmerkung

Unterstützung für benutzerdefinierte Speicherbelegungen Der native Speicherprofiler sammelt auf die Speicherbelegung bezogene ETW--Ereignisdaten, die zur Laufzeit ausgegeben werden. Allocatoren im CRT- und Windows-SDK wurden auf Quellcode-Ebene annotiert, sodass ihre Zuordnungsdaten erfasst werden können. Wenn Sie Ihre eigenen Zuweisungen schreiben, kann jede Funktion, die einen Zeiger auf neu zugewiesenen Heapspeicher zurückgibt, mit __declspec(allocator) ergänzt werden, wie in diesem Beispiel für myMalloc zu sehen ist:

__declspec(allocator) void* myMalloc(size_t size)

Sammeln von Speicherauslastungsdaten

  1. Öffnen Sie das Projekt, das Sie in Visual Studio debuggen möchten, und legen Sie an der Stelle, an der Sie mit der Untersuchung der Speicherauslastung beginnen möchten, einen Haltepunkt in Ihrer App fest.

    Wenn Sie einen Bereich haben, in dem Sie ein Speicherproblem vermuten, legen Sie den ersten Haltepunkt fest, bevor das Speicherproblem auftritt.

    Tipp

    Da es schwierig sein kann, das Speicherprofil eines Vorgangs zu erfassen, der Sie interessiert, wenn Ihre App häufig Speicher zuweist und den Speicher de-ordnet, legen Sie Haltepunkte am Anfang und Ende des Vorgangs fest (oder durchlaufen Sie den Vorgang), um den genauen Punkt zu finden, an dem sich der Speicher geändert hat.

  2. Legen Sie einen zweiten Haltepunkt am Ende der Funktion oder des Codes fest, die Sie analysieren möchten (oder nachdem ein verdächtiges Speicherproblem auftritt).

  3. Das Fenster Diagnosetools wird automatisch angezeigt, es sei denn, Sie haben es deaktiviert. Um das Fenster erneut anzuzeigen, klicken Sie auf Debuggen>Windows>Diagnosetools anzeigen.

  4. Wählen Sie Speicherauslastung mit der Einstellung Auswahltools auf der Symbolleiste aus.

    Screenshot der Diagnosetools.

    Screenshot der Diagnosetools.

  5. Klicken Sie auf Debuggen / Debugging starten (oder auf Start auf der Symbolleiste oder auf F5).

    Nach Abschluss des Ladens der App wird die Zusammenfassungsansicht der Diagnosetools angezeigt.

    Screenshot: Diagnosetools, Registerkarte „Zusammenfassung“.

    Anmerkung

    Da das Erfassen von Speicherdaten die Debugleistung Ihrer systemeigenen Apps oder Ihrer Apps mit gemischtem Modus beeinträchtigen kann, sind Speichermomentaufnahmen standardmäßig deaktiviert. Um Momentaufnahmen in systemeigenen oder gemischten Apps zu aktivieren, starten Sie eine Debugsitzung (Tastenkombination: F5). Wenn das Fenster Diagnosetools angezeigt wird, wählen Sie die Registerkarte Speicherauslastung und dann Heap-Profilerstellungaus.

    Screenshot der Option

    Beenden (Tastenkombination: Umschalttaste+F5) und Debuggen neu starten.

    Screenshot: Diagnosetools, Registerkarte „Zusammenfassung“.

    Anmerkung

    Da das Sammeln von Speicherdaten die Debugging-Performance Ihrer nativen oder gemischten Apps beeinträchtigen kann, sind Speicherschnappschüsse standardmäßig deaktiviert. Um Momentaufnahmen in systemeigenen oder gemischten Apps zu aktivieren, starten Sie eine Debugsitzung (Tastenkombination: F5). Wenn das Fenster Diagnosetools angezeigt wird, wählen Sie die Registerkarte Speicherauslastung und dann Heap-Profilerstellungaus.

    Screenshot der Option

    Beenden (Tastenkombination: Umschalttaste+F5) und Debuggen neu starten.

  6. Um eine Momentaufnahme zu Beginn der Debugsitzung zu erstellen, wählen Sie auf der Übersichtssymbolleiste Speicherauslastung die Option Momentaufnahme erstellen aus. (Es kann auch hilfreich sein, einen Haltepunkt hier festzulegen.)

    Screenshot der Schaltfläche

    Screenshot der Schaltfläche

    Tipp

    Um einen Basisplan für Speichervergleiche zu erstellen, sollten Sie am Anfang der Debugsitzung eine Momentaufnahme erstellen.

  7. Führen Sie das Szenario aus, bei dem Ihr erster Haltepunkt erreicht wird.

  8. Während der Debugger am ersten Haltepunkt angehalten ist, wählen Sie im Zusammenfassungswerkzeug Speicherauslastung die Option Momentaufnahme erstellen aus.

  9. Drücken Sie F5, um die App bis zum zweiten Haltepunkt auszuführen.

  10. Erstellen Sie nun eine weitere Momentaufnahme.

    An diesem Punkt können Sie mit der Analyse der Daten beginnen.

    Wenn Sie Probleme beim Sammeln oder Anzeigen von Daten haben, lesen Sie Behandeln von Profilerstellungsfehlern und Beheben von Problemen.

Analysieren von Speichernutzungsdaten

Die Zeilen der Speicherauslastungs-Übersichtstabelle führen die Momentaufnahmen auf, die Sie während der Debugsitzung erstellt haben, und bieten Links zu detaillierteren Ansichten.

Screenshot der Tabelle

Screenshot der Tabelle

Der Name der Spalte hängt vom Debugmodus ab, den Sie in den Projekteigenschaften auswählen: .NET, nativ oder gemischt (sowohl .NET als auch nativ).

  • Die Spalte Objects (Diff) (.NET) oder Allocations (Diff) (C++) zeigt die Anzahl der Objekte in .NET oder systemeigenem Speicher an, wenn die Momentaufnahme erstellt wurde.

  • Die Spalte Heapgröße (Diff) zeigt die Anzahl der Bytes in den .NET- und nativen Heaps

Wenn Sie mehrere Momentaufnahmen erstellt haben, enthalten die Zellen der Zusammenfassungstabelle die Änderung des Werts zwischen der Zeilenmomentaufnahme und der vorherigen Momentaufnahme.

Um die Speicherauslastung zu analysieren, klicken Sie auf einen der Links, über die ein detaillierter Bericht über die Speicherauslastung geöffnet wird:

  • Um Details des Unterschieds zwischen der aktuellen Momentaufnahme und der vorherigen Momentaufnahme anzuzeigen, wählen Sie den Änderungslink links neben dem Pfeil aus (Arbeitsspeicherauslastungssteigerung). Ein roter Pfeil zeigt eine Erhöhung der Speicherauslastung an, und ein grüner Pfeil zeigt eine Abnahme an.

Tipp

Um Speicherprobleme schneller zu identifizieren, werden die Diff-Berichte nach Objekttypen sortiert, die sich in der Gesamtanzahl am meisten erhöht haben (klicken Sie auf den Änderungslink in der Spalte Objekte (Diff)), oder die, in der sich die Gesamtheapgröße am meisten erhöht hat (klicken Sie auf den Änderungslink in der Spalte Heap-Größe (Diff)).

  • Um Details nur der ausgewählten Momentaufnahme anzuzeigen, klicken Sie auf den Link ohne Änderungen.

    Der Bericht wird in einem separaten Fenster angezeigt.

Berichte zu den verwalteten Typen

Wählen Sie den aktuellen Link einer Objects (Diff) Zelle in der Zusammenfassungstabelle "Speicherauslastung" aus.

Screenshot: Bericht zu verwalteten Typen.

Anmerkung

Für .NET-Code ist das Symbol Ansichtsinstanzen (Das Instanzsymbol in der Spalte „Objekttyp“) nur verfügbar, wenn Sie das Debugger-integrierte Speicherauslastungstool verwenden oder wenn Sie eine Heap-Momentaufnahme öffnen und Verwalteten Arbeitsspeicher debuggen auswählen.

Im oberen Bereich werden Anzahl und Größe der Typen in der Momentaufnahme angezeigt, einschließlich der Größe aller Objekte, auf die der Typ verweist (Inklusive Größe).

Die Baumstruktur Pfade zum Stamm im unteren Bereich zeigt die Objekte an, die auf den im oberen Bereich ausgewählten Typ verweisen. Der .NET Garbage Collector bereinigt den Speicher für ein Objekt nur, wenn der letzte Typ, der darauf verweist, freigegeben wurde. Weitere Informationen zur Verwendung der Pfade zum Stamm--Struktur finden Sie unter Analysieren des langsamsten Pfads zum Stamm.

Screenshot: Bericht zu verwalteten Typen.

Im oberen Bereich werden Anzahl und Größe der Typen in der Momentaufnahme angezeigt, einschließlich der Größe aller Objekte, auf die der Typ verweist (Inklusive Größe).

Die Baumstruktur Pfade zum Stamm im unteren Bereich zeigt die Objekte an, die auf den im oberen Bereich ausgewählten Typ verweisen. Der .NET Garbage Collector bereinigt den Speicher für ein Objekt nur, wenn der letzte Typ, der darauf verweist, freigegeben wurde.

Die Baumstruktur Referenzierte Typen enthält die Verweise, die von dem Typ, der im oberen Bereich ausgewählt ist, gehalten werden.

Screenshot des Berichts

Die Baumstruktur Referenzierte Typen enthält die Verweise, die von dem Typ, der im oberen Bereich ausgewählt ist, gehalten werden.

Screenshot des Berichts

Um die Instanzen eines ausgewählten Typs im oberen Bereich anzuzeigen, klicken Sie neben dem Objekttyp auf das Symbol Instanzen anzeigen.

Screenshot: Ansicht „Instanzen“ im Speichernutzungstool.

Die Ansicht Instanzen zeigt die Instanzen des ausgewählten Objekts in der Momentaufnahme des oberen Bereichs an. Die Bereiche Pfade zum Stamm und Referenzierte Objekte zeigen die Objekte an, die auf die ausgewählte Instanz verweisen, sowie die Typen, auf die die ausgewählte Instanz verweist. Wenn der Debugger zu dem Zeitpunkt beendet wird, an dem die Momentaufnahme erstellt wurde, können Sie auf die Zelle Wert zeigen, um die Werte des Objekts in einer QuickInfo anzuzeigen.

Screenshot der Ansicht

Die Ansicht Instanzen zeigt die Instanzen des ausgewählten Objekts in der Momentaufnahme des oberen Bereichs an. Im Bereich "Pfade zu Root-" und "Referenzierte Objekte" werden die Objekte angezeigt, die auf die ausgewählte Instanz verweisen, sowie die Typen, auf die die ausgewählte Instanz verweist. Wenn der Debugger zu dem Zeitpunkt beendet wird, an dem die Momentaufnahme erstellt wurde, können Sie auf die Zelle Wert zeigen, um die Werte des Objekts in einer QuickInfo anzuzeigen.

Berichte zu nativen Typen

Wählen Sie die aktuelle Verknüpfung einer Zuweisungen (Diff.)- oder Heapgröße (Diff.)-Zelle aus der Zusammenfassungstabelle zur Speicherauslastung im Fenster Diagnosetools aus.

Screenshot: Ansicht „Nativer Typ“.

Screenshot: Ansicht „Nativer Typ“.

Die Typenansicht zeigt die Anzahl und Größe der Typen in der Momentaufnahme an.

  • Wählen Sie das Symbol Instanzen anzeigen neben einem ausgewählten Typ aus, um Informationen zu den Objekten des ausgewählten Typs in der Momentaufnahme anzuzeigen.

    Die Ansicht Instanzen zeigt jede Instanz des ausgewählten Typs an. Durch Auswahl einer Instanz wird die Aufrufliste angezeigt, welche die Erstellung der Instanz im Bereich Belegungsaufrufliste bewirkt hat. (Diese Informationen sind nur beim Debuggen verfügbar.)

    Screenshot: Ansicht „Instanzen“ und Bereich „Belegungsaufrufliste“.

  • Wählen Sie das Instanzsymbol (Das Instanzsymbol in der Spalte ) eines ausgewählten Typs aus, um Informationen zu den Objekten des ausgewählten Typs in der Momentaufnahme anzuzeigen.

    Die Ansicht Instanzen zeigt jede Instanz des ausgewählten Typs an. Durch Auswahl einer Instanz wird die Aufrufliste angezeigt, welche die Erstellung der Instanz im Bereich Belegungsaufrufliste bewirkt hat.

    Screenshot: Ansicht „Instanzen“ und Bereich „Belegungsaufrufliste“.

  • Wählen Sie Stack aus, um den Zuordnungsstack für den ausgewählten Typ anzuzeigen.

    Screenshot der Stapelansicht.

  • Wählen Sie in der Liste Ansichtsmodus die Option Stapelansicht aus, um den Zuweisungsstapel für den ausgewählten Typ anzuzeigen.

    Screenshot der Stapelansicht.

Einblicke zur Speicherauslastung

Für verwalteten Speicher bietet das Speicheranalysetool auch mehrere integrierte leistungsstarke automatische Erkenntnisse. Wählen Sie die Registerkarte Erkenntnisse in den Berichten vom Typ „Verwaltet“ aus, um die anwendbaren automatischen Erkenntnisse anzuzeigen, z. B. Doppelte Zeichenfolgen, Sparsearrays und Ereignishandlerverluste.

Screenshot der Übersicht im Tool

Im Abschnitt duplizierte Zeichenfolgen wird die Liste der Zeichenfolgen angezeigt, die mehrmals auf dem Heap zugeordnet werden. Darüber hinaus zeigt dieser Abschnitt den gesamten verschwendeten Arbeitsspeicher, d. h. die (Anzahl der Instanzen - 1) mal die Größe der Zeichenfolge.

Der Abschnitt Sparse Arrays zeigt Arrays an, die hauptsächlich mit Nullelementen gefüllt sind, was ineffizient in Bezug auf Leistung und Speicherauslastung sein kann. Das Speicheranalysetool erkennt diese Arrays automatisch und zeigt Ihnen, wie viel Arbeitsspeicher aufgrund dieser Nullwerte verschwendet wird.

Der Abschnitt Ereignishandlerlecks, der in Visual Studio 2022, Version 17.9 Preview 1 verfügbar ist, zeigt potenzielle Speicherlecks an, die auftreten können, wenn ein Objekt das Ereignis eines anderen Objekts abonniert. Wenn der Herausgeber des Ereignisses den Abonnenten überdauert, bleibt der Abonnent bestehen, auch wenn es keine weiteren Verweise auf ihn gibt. Dies kann zu Speicherlecks führen, bei denen nicht verwendeter Arbeitsspeicher nicht ordnungsgemäß freigegeben wird, was dazu führt, dass die Anwendung im Laufe der Zeit mehr und mehr Arbeitsspeicher verwendet.

Für bestimmte Typen sind Felder bekannt, die gelesen werden können, um die Größe des nativen Speichers zu bestimmen, zu dem sie gehören. Auf dem Tab Insights werden gefälschte native Speicher-Knoten im Objektdiagramm angezeigt, die von ihren übergeordneten Objekten beibehalten werden, sodass die Benutzeroberfläche sie erkennt und ihre Größe sowie die Referenzstruktur anzeigt.

Screenshot der nativen Ansicht zu Erkenntnissen im Speicherauslastungstool.

(Diff) Änderungsberichte

  • Wählen Sie den Änderungslink in einer Zelle der Zusammenfassungstabelle der Registerkarte Speicherauslastung im Fenster Diagnosetools aus.

    Screenshot: Auswählen eines Änderungslinks in einer Zelle.

    Screenshot: Link zum Auswählen einer Änderung in einer Zelle.

  • Wählen Sie eine Momentaufnahme aus der Liste Vergleichen mit Liste eines verwalteten oder systemeigenen Berichts aus.

    Screenshot: Auswählen einer Momentaufnahme aus der Liste „Vergleichen mit“.

    Screenshot: Auswählen einer Momentaufnahme aus der Liste „Vergleichen mit“.

Der Änderungsbericht fügt dem Basisbericht Spalten (durch (Diff) gekennzeichnet) hinzu, die den Unterschied zwischen der Basismomentaufnahme und der Vergleichsmomentaufnahme anzeigen. So könnte ein Unterschiedsbericht für die Ansicht mit nativen Typen aussehen:

Screenshot: Ansicht „Unterschiede bei nativen Typen“

Screenshot: Ansicht „Unterschiede bei nativen Typen“

Im oberen Bereich werden Anzahl und Größe der Typen in der Momentaufnahme angezeigt, einschließlich der Größe aller Objekte, auf die der Typ verweist (Umfassende Größe).

Blogs und Videos

Analysieren Sie die CPU und den Arbeitsspeicher beim Debuggen

Visual C++-Blog: Speicherprofilerstellung in Visual C++ 2015

Nächste Schritte

In diesem Lernprogramm haben Sie gelernt, wie Sie Speichernutzungsdaten sammeln und analysieren. Wenn Sie bereits die Tour des Profilersabgeschlossen haben, sollten Sie sich über einen allgemeinen Ansatz zur Optimierung von Code mithilfe der Profilerstellungstools informieren.

In diesem Lernprogramm haben Sie gelernt, wie Sie Beim Debuggen Speichernutzungsdaten sammeln und analysieren. Möglicherweise möchten Sie mehr über die Analyse der Speicherauslastung in Releasebuilds mithilfe des Performance Profiler erfahren.