Mierzenie użycia pamięci w programie Visual Studio (C#, Visual Basic, C++, F#)

Znajdowanie przecieków pamięci i nieefektywnej pamięci podczas debugowania za pomocą narzędzia diagnostycznego użycia pamięci zintegrowanej z debugerem. Narzędzie Użycie pamięci umożliwia wykonywanie co najmniej jednej migawki sterty pamięci zarządzanej i natywnej, aby ułatwić zrozumienie wpływu użycia pamięci na typy obiektów. Możesz również analizować użycie pamięci bez dołączonego debugera lub kierowania uruchomionej aplikacji. Aby uzyskać więcej informacji, zobacz Uruchamianie narzędzi profilowania z debugerem lub bez tego debugera. Aby uzyskać informacje na temat wybierania najlepszego narzędzia do analizy pamięci dla Twoich potrzeb, zobacz Wybieranie narzędzia do analizy pamięci.

Chociaż migawki pamięci można zbierać w dowolnym momencie w narzędziu Użycie pamięci, możesz użyć debugera programu Visual Studio, aby kontrolować sposób wykonywania aplikacji podczas badania problemów z wydajnością. Ustawianie punktów przerwania, kroków, przerwania wszystkich i innych akcji debugera może pomóc w skoncentrowaniu badań wydajności na ścieżkach kodu, które są najbardziej istotne. Wykonanie tych akcji podczas działania aplikacji może wyeliminować szum z kodu, który cię nie interesuje i może znacznie skrócić czas potrzebny do zdiagnozowania problemu.

Ważne

Zintegrowane z debugerem narzędzia diagnostyczne są obsługiwane w przypadku programowania na platformie .NET w programie Visual Studio, w tym ASP.NET, ASP.NET Core, programowania natywnego/C++ oraz aplikacji trybu mieszanego (.NET i natywnego). System Windows 8 lub nowszy jest wymagany do uruchamiania narzędzi profilowania przy użyciu debugera (okno Narzędzia diagnostyczne).

Ten samouczek obejmuje następujące kroki:

  • Tworzenie migawek pamięci
  • Analizowanie danych użycia pamięci

Jeśli użycie pamięci nie daje potrzebnych danych, inne narzędzia profilowania w profilerze wydajności udostępniają różne rodzaje informacji, które mogą być przydatne. W wielu przypadkach wąskie gardło wydajności aplikacji może być spowodowane przez coś innego niż pamięć, takie jak procesor CPU, renderowanie interfejsu użytkownika lub czas żądania sieciowego.

Uwaga

Niestandardowa obsługa alokatora Profiler pamięci natywnej działa przez zbieranie danych zdarzenia ETW alokacji emitowanych w czasie wykonywania. Alokatory w zestawach CRT i Windows SDK zostały oznaczone adnotacjami na poziomie źródła, aby można było przechwycić ich dane alokacji. Jeśli piszesz własne alokatory, wszystkie funkcje, które zwracają wskaźnik do nowo przydzielonej pamięci stertowej, mogą być ozdobione __declspec (alokator), jak pokazano w tym przykładzie dla myMalloc:

__declspec(allocator) void* myMalloc(size_t size)

Zbieranie danych użycia pamięci

  1. Otwórz projekt, który chcesz debugować w programie Visual Studio, i ustaw punkt przerwania w aplikacji w punkcie, w którym chcesz rozpocząć badanie użycia pamięci.

    Jeśli masz obszar, w którym podejrzewasz problem z pamięcią, ustaw pierwszy punkt przerwania przed wystąpieniem problemu z pamięcią.

    Napiwek

    Ponieważ może to być trudne do przechwycenia profilu pamięci operacji, która interesuje Cię, gdy aplikacja często przydziela i delokuje pamięć, ustawia punkty przerwania na początku i na końcu operacji (lub krok po operacji), aby znaleźć dokładny punkt, który zmienił się pamięci.

  2. Ustaw drugi punkt przerwania na końcu funkcji lub regionu kodu, który chcesz przeanalizować (lub po wystąpieniu podejrzanego problemu z pamięcią).

  3. Zostanie wyświetlone okno Narzędzia diagnostyczne automatycznie, chyba że zostało wyłączone. Aby ponownie wyświetlić okno, kliknij pozycję Debuguj>narzędzia diagnostyczne Pokaż system Windows.>

  4. Wybierz pozycję Użycie pamięci z ustawieniem Wybierz narzędzia na pasku narzędzi.

    Screenshot of Diagnostics Tools.

    Screenshot of Diagnostics Tools.

  5. Kliknij pozycję Debuguj/Rozpocznij debugowanie (lub Uruchom na pasku narzędzi lub F5).

    Po zakończeniu ładowania aplikacji zostanie wyświetlony widok Podsumowanie narzędzi diagnostycznych.

    Screenshot of Diagnostics Tools Summary Tab.

    Uwaga

    Ponieważ zbieranie danych pamięci może mieć wpływ na wydajność debugowania aplikacji natywnych lub mieszanych, migawki pamięci są domyślnie wyłączone. Aby włączyć migawki w aplikacjach w trybie natywnym lub mieszanym, uruchom sesję debugowania (klawisz skrótu: F5). Po wyświetleniu okna Narzędzia diagnostyczne wybierz kartę Użycie pamięci, a następnie wybierz pozycję Profilowanie sterty.

    Screenshot of Enable snapshots.

    Zatrzymaj (klawisz skrótu: Shift+F5) i uruchom ponownie debugowanie.

    Screenshot of Diagnostics Tools Summary Tab.

    Uwaga

    Ponieważ zbieranie danych pamięci może mieć wpływ na wydajność debugowania aplikacji natywnych lub mieszanych, migawki pamięci są domyślnie wyłączone. Aby włączyć migawki w aplikacjach w trybie natywnym lub mieszanym, uruchom sesję debugowania (klawisz skrótu: F5). Po wyświetleniu okna Narzędzia diagnostyczne wybierz kartę Użycie pamięci, a następnie wybierz pozycję Profilowanie sterty.

    Screenshot of Enable snapshots.

    Zatrzymaj (klawisz skrótu: Shift+F5) i uruchom ponownie debugowanie.

  6. Aby utworzyć migawkę na początku sesji debugowania, wybierz pozycję Utwórz migawkę na pasku narzędzi podsumowania Użycie pamięci. (Może to również pomóc w ustawieniu punktu przerwania).

    Screenshot of Take Snapshot button.

    Screenshot of Take Snapshot button.

    Napiwek

    Aby utworzyć punkt odniesienia dla porównań pamięci, rozważ utworzenie migawki na początku sesji debugowania.

  7. Uruchom scenariusz, który spowoduje trafienie pierwszego punktu przerwania.

  8. Podczas gdy debuger jest wstrzymany w pierwszym punkcie przerwania, wybierz pozycję Wykonaj migawkę na pasku narzędzi podsumowania Użycie pamięci.

  9. Naciśnij klawisz F5 , aby uruchomić aplikację w drugim punkcie przerwania.

  10. Teraz wykonaj kolejną migawkę.

    W tym momencie możesz rozpocząć analizowanie danych.

    Jeśli masz problemy ze zbieraniem lub wyświetlaniem danych, zobacz Rozwiązywanie problemów z błędami profilowania i rozwiązywanie problemów.

Analizowanie danych użycia pamięci

Wiersze tabeli podsumowania Użycie pamięci zawierają listę migawek wykonanych podczas sesji debugowania i linki do bardziej szczegółowych widoków.

Screenshot of Memory Usage table.

Screenshot of Memory Usage table.

Nazwa kolumny zależy od trybu debugowania wybranego we właściwościach projektu: .NET, native lub mieszanych (zarówno .NET, jak i native).

  • Kolumny Objects (Diff) i Allocations (Różnice) wyświetlają liczbę obiektów na platformie .NET i pamięci natywnej podczas tworzenia migawki.

  • W kolumnie Rozmiar sterty (różnice) jest wyświetlana liczba bajtów na platformie .NET i natywnych stertach

Po utworzeniu wielu migawek komórki tabeli podsumowania zawierają zmianę wartości między migawką wiersza a poprzednią migawką.

Aby przeanalizować użycie pamięci, kliknij jeden z linków, który otwiera szczegółowy raport użycia pamięci:

  • Aby wyświetlić szczegóły różnicy między bieżącą migawką a poprzednią migawką, wybierz link zmiany z lewej strony strzałki (Memory Usage Increase). Czerwona strzałka wskazuje wzrost użycia pamięci, a zielona strzałka wskazuje spadek.

Napiwek

Aby ułatwić szybsze identyfikowanie problemów z pamięcią, raporty różnic są sortowane według typów obiektów, które zwiększyły najwięcej ogólnej liczby (kliknij link zmiany w kolumnie Obiekty (różnice) lub które zwiększyły najbardziej ogólny rozmiar sterty (kliknij link zmiany w kolumnie Rozmiar sterty (różnice).

  • Aby wyświetlić szczegóły tylko wybranej migawki, kliknij link bez zmian.

    Raport zostanie wyświetlony w osobnym oknie.

Raporty typów zarządzanych

Wybierz bieżący link komórki Obiekty (różnice) lub Alokacje (różnice) w tabeli podsumowania Użycie pamięci.

Screenshot of managed type report.

Screenshot of managed type report.

Górne okienko przedstawia liczbę i rozmiar typów w migawce, w tym rozmiar wszystkich obiektów, do których odwołuje się typ (rozmiar inkluzywny).

Ścieżki do drzewa głównego w dolnym okienku wyświetla obiekty odwołujące się do typu wybranego w górnym okienku. Moduł odśmieceń pamięci platformy .NET czyści pamięć dla obiektu tylko wtedy, gdy ostatni typ odwołujący się do niego został zwolniony.

Drzewo Obiekty , do których odwołuje się wyświetlanie odwołań przechowywanych przez typ wybrany w górnym okienku.

Screenshot of Referenced Objects report.

W drzewie Typy odwołań są wyświetlane odwołania przechowywane przez typ wybrany w górnym okienku.

Screenshot of Referenced Objects report.

Aby wyświetlić wystąpienia wybranego typu w górnym okienku, kliknij pozycję "Wyświetl wystąpienia" obok typu obiektu.

Screenshot of the Instances view in the Memory Usage tool.

Screenshot of the Instances view in the Memory Usage tool.

Widok Wystąpienia wyświetla wystąpienia wybranego obiektu w migawki w górnym okienku. W okienku Ścieżki do obiektów głównych i przywołynych są wyświetlane obiekty odwołujące się do wybranego wystąpienia oraz typy, do których odwołuje się wybrane wystąpienie. Po zatrzymaniu debugera w punkcie, w którym utworzono migawkę, możesz umieścić kursor na komórce Wartość , aby wyświetlić wartości obiektu w poradzie narzędzia.

Raporty typów natywnych

Wybierz bieżący link komórki Alokacje (różnice) lub Rozmiar sterty (Różnice) w tabeli podsumowania Użycie pamięci okna Narzędzia diagnostyczne.

Screenshot of Native Type View.

Screenshot of Native Type View.

Widok typy wyświetla liczbę i rozmiar typów w migawce.

  • Wybierz ikonę wystąpień (The instance icon in the Object Type column) wybranego typu, aby wyświetlić informacje o obiektach wybranego typu w migawki.

    Widok Wystąpienia wyświetla każde wystąpienie wybranego typu. Wybranie wystąpienia powoduje wyświetlenie stosu wywołań, który spowodował utworzenie wystąpienia w okienku stosu wywołań alokacji.

    Screenshot of the Instances view and Allocation Call Stack pane.

  • Wybierz pozycję Wyświetl wystąpienia obok wybranego typu, aby wyświetlić informacje o obiektach wybranego typu w migawki.

    Widok Wystąpienia wyświetla każde wystąpienie wybranego typu. Wybranie wystąpienia powoduje wyświetlenie stosu wywołań, który spowodował utworzenie wystąpienia w okienku stosu wywołań alokacji.

    Screenshot of the Instances view and Allocation Call Stack pane.

  • Wybierz pozycję Widok stosów na liście Tryb widoku, aby wyświetlić stos alokacji dla wybranego typu.

    Screenshot of Stacks view.

  • Wybierz pozycję Stosy , aby wyświetlić stos alokacji dla wybranego typu.

    Screenshot of Stacks view.

Szczegółowe informacje użycia pamięci

W przypadku pamięci zarządzanej narzędzie Analizy pamięci zapewnia również wiele zaawansowanych wbudowanych funkcji automatycznego wglądu w szczegółowe informacje. Wybierz kartę Szczegółowe informacje w raportach Typy zarządzane i wyświetla odpowiednie automatyczne szczegółowe informacje, takie jak zduplikowane ciągi, tablice rozrzedlone i przecieki obsługi zdarzeń.

Screenshot of the insight view in the Memory Usage tool.

Sekcja Zduplikowane ciągi zawiera listę ciągów, które są przydzielane wiele razy na stercie. Ponadto w tej sekcji przedstawiono łączną ilość zmarnowanej pamięci, czyli (liczba wystąpień — 1) razy większy od rozmiaru ciągu.

Sekcja Rozrzedzone tablice zawiera tablice, które są w większości wypełnione elementami zerowymi, co może być nieefektywne pod względem wydajności i użycia pamięci. Narzędzie do analizy pamięci automatycznie wykryje te tablice i pokaże, ile pamięci jest marnowane z powodu tych wartości zerowych.

Sekcja Przecieki obsługi zdarzeń dostępna w programie Visual Studio 2022 w wersji 17.9 (wersja zapoznawcza 1) pokazuje potencjalne przecieki pamięci, które mogą wystąpić, gdy jeden obiekt subskrybuje zdarzenie innego obiektu. Jeśli wydawca zdarzenia przeżyje subskrybenta, subskrybent pozostaje żywy, nawet jeśli nie ma do niego żadnych innych odwołań. Może to prowadzić do przecieków pamięci, w których nieużywana pamięć nie jest prawidłowo zwalniana, co powoduje, że aplikacja będzie używać coraz większej ilości pamięci wraz z upływem czasu.

Niektóre typy są znane z pól, które można odczytać, aby określić rozmiar pamięci natywnej, na której się trzyma. Karta Szczegółowe informacje pokazuje fałszywe natywne węzły pamięci na grafie obiektów, które są zachowywane przez ich obiekty nadrzędne, tak aby interfejs użytkownika je rozpoznał i wyświetlił ich rozmiar i graf referencyjny.

Screenshot of the native insight view in the Memory Usage tool.

Zmienianie (różnice) raportów

  • Wybierz link zmiany w komórce tabeli podsumowania karty Użycie pamięci w oknie Narzędzia diagnostyczne.

    Screenshot of Choose a change link in a cell.

    Screenshot of Choose a change link in a cell.

  • Wybierz migawkę na liście Porównaj z raportem zarządzanym lub natywnym.

    Screenshot of Choose a snapshot from the Compare To list.

    Screenshot of Choose a snapshot from the Compare with list.

Raport zmiany dodaje kolumny (oznaczone wartością (Różnice) do raportu podstawowego, które pokazują różnicę między podstawową wartością migawki a migawką porównania. Oto jak może wyglądać raport różnic widoku typu natywnego:

Screenshot of Native Types Diff View.

Screenshot of Native Types Diff View.

Blogi i wideo

Analizowanie procesora CPU i pamięci podczas debugowania

Blog języka Visual C++: profilowanie pamięci w programie Visual C++ 2015

Następne kroki

W tym samouczku przedstawiono sposób zbierania i analizowania danych użycia pamięci. Jeśli przewodnik po profilerze został już ukończony, warto zapoznać się z ogólnym podejściem do optymalizacji kodu przy użyciu narzędzi profilowania.

W tym samouczku przedstawiono sposób zbierania i analizowania danych użycia pamięci podczas debugowania. Możesz dowiedzieć się więcej na temat analizowania użycia pamięci w kompilacjach wydań przy użyciu profilera wydajności.