Udostępnij za pośrednictwem


Niestandardowe zdarzenia ETW sterty natywnej

Program Visual Studio zawiera różne narzędzia profilowania i diagnostyki, w tym profiler pamięci natywnej. Ten profiler zaczepia zdarzenia ETW od dostawcy sterty i zapewnia analizę sposobu przydzielania i użycia pamięci. Domyślnie to narzędzie może analizować tylko alokacje wykonane ze standardowego sterty systemu Windows, a wszystkie alokacje poza tą natywną stertą nie będą wyświetlane.

Istnieje wiele przypadków, w których można chcieć użyć własnej sterty niestandardowej i uniknąć obciążenia alokacji ze standardowej sterty. Możesz na przykład użyć funkcji VirtualAlloc , aby przydzielić dużą ilość pamięci na początku aplikacji lub gry, a następnie zarządzać własnymi blokami na tej liście. W tym scenariuszu narzędzie profilera pamięci będzie widzieć tylko tę początkową alokację, a nie niestandardowe zarządzanie wykonywane wewnątrz fragmentu pamięci. Jednak przy użyciu niestandardowego natywnego dostawcy ETW sterty można poinformować narzędzie o wszelkich alokacjach spoza standardowej sterty.

Na przykład w projekcie, podobnie jak w poniższym miejscu, gdzie MemoryPool jest stertą niestandardową, zobaczysz tylko jedną alokację na stercie systemu Windows:

class Foo
{
public:
    int x, y;
};

...

// MemoryPool is a custom managed heap, which allocates 8192 bytes
// on the standard Windows Heap named "Windows NT"
MemoryPool<Foo, 8192> mPool;

// the "allocate" method requests memory from the pool created above
// and is cast to an object of type Foo, shown above
Foo* pFoo1 = (Foo*)mPool.allocate();
Foo* pFoo2 = (Foo*)mPool.allocate();
Foo* pFoo3 = (Foo*)mPool.allocate();

Migawka z narzędzia Użycie pamięci bez niestandardowego śledzenia sterty pokazuje tylko pojedynczą alokację bajtów 8192 i żaden z niestandardowych alokacji wykonanych przez pulę:

Windows heap allocation

Wykonując poniższe kroki, możemy użyć tego samego narzędzia do śledzenia użycia pamięci w naszej niestandardowej stercie.

Jak stosować

Tę bibliotekę można łatwo używać w językach C i C++.

  1. Dołącz nagłówek niestandardowego dostawcy ETW sterty:

    #include <VSCustomNativeHeapEtwProvider.h>
    
  2. __declspec(allocator) Dodaj dekorator do dowolnej funkcji w niestandardowym menedżerze sterty, która zwraca wskaźnik do nowo przydzielonej pamięci sterty. Ten dekorator umożliwia narzędziu poprawne identyfikowanie typu zwracanej pamięci. Na przykład:

    __declspec(allocator) void *MyMalloc(size_t size);
    

    Uwaga

    Ten dekorator poinformuje kompilator, że ta funkcja jest wywołaniem alokatora. Każde wywołanie funkcji zwróci adres obiektu callite, rozmiar instrukcji wywołania i typId nowego obiektu do nowego S_HEAPALLOCSITE symbolu. Po przydzieleniu stosu wywołań system Windows będzie emitować zdarzenie ETW z tych informacji. Narzędzie profilera pamięci przeprowadzi stos wywołań wyszukujący zwracany adres pasujący S_HEAPALLOCSITE do symbolu, a informacje typeId w symbolu są używane do wyświetlania typu środowiska uruchomieniowego alokacji.

    Krótko mówiąc, oznacza to, że wywołanie, które wygląda następująco (B*)(A*)MyMalloc(sizeof(B)) , będzie wyświetlane w narzędziu jako typ B, a nie void lub A.

  3. W przypadku języka C++utwórz VSHeapTracker::CHeapTracker obiekt, podając nazwę sterta, która będzie wyświetlana w narzędziu profilowania:

    auto pHeapTracker = std::make_unique<VSHeapTracker::CHeapTracker>("MyCustomHeap");
    

    Jeśli używasz języka C, użyj OpenHeapTracker funkcji . Ta funkcja zwróci uchwyt, który będzie używany podczas wywoływania innych funkcji śledzenia:

    VSHeapTrackerHandle hHeapTracker = OpenHeapTracker("MyHeap");
    
  4. W przypadku przydzielania pamięci przy użyciu funkcji niestandardowej wywołaj AllocateEvent metodę (C++) lub VSHeapTrackerAllocateEvent (C), przekazując wskaźnik do pamięci i jej rozmiaru, aby śledzić alokację:

    pHeapTracker->AllocateEvent(memPtr, size);
    

    lub

    VSHeapTrackerAllocateEvent(hHeapTracker, memPtr, size);
    

    Ważne

    Nie zapomnij o oznaczeniu niestandardowej funkcji alokatora za pomocą dekoratora opisanego __declspec(allocator) wcześniej.

  5. W przypadku cofnięcia przydziału pamięci przy użyciu funkcji niestandardowej wywołaj DeallocateEvent funkcję (C++) lub VSHeapTracerDeallocateEvent (C), przekazując wskaźnik do pamięci, aby śledzić cofanie przydziału:

    pHeapTracker->DeallocateEvent(memPtr);
    

    or:

    VSHeapTrackerDeallocateEvent(hHeapTracker, memPtr);
    
  6. Podczas ponownego przydzielania pamięci przy użyciu funkcji niestandardowej wywołaj ReallocateEvent metodę (C++) lub VSHeapReallocateEvent (C), przekazując wskaźnik do nowej pamięci, rozmiar alokacji i wskaźnik do starej pamięci:

    pHeapTracker->ReallocateEvent(memPtrNew, size, memPtrOld);
    

    or:

    VSHeapTrackerReallocateEvent(hHeapTracker, memPtrNew, size, memPtrOld);
    
  7. Na koniec, aby zamknąć i wyczyścić niestandardowy monitor stert w języku C++, użyj CHeapTracker destruktora, ręcznie lub za pomocą standardowych reguł określania zakresu lub CloseHeapTracker funkcji w języku C:

    delete pHeapTracker;
    

    or:

    CloseHeapTracker(hHeapTracker);
    

Śledzenie użycia pamięci

Dzięki tym wywołaniom niestandardowe użycie stert można teraz śledzić przy użyciu standardowego narzędzia Użycie pamięci w programie Visual Studio. Aby uzyskać więcej informacji na temat korzystania z tego narzędzia, zobacz dokumentację użycie pamięci. Upewnij się, że włączono profilowanie stert z migawkami. W przeciwnym razie nie będzie wyświetlane niestandardowe użycie stert.

Enable Heap Profiling

Aby wyświetlić niestandardowe śledzenie stert, użyj listy rozwijanej Sterta znajdującej się w prawym górnym rogu okna Migawka , aby zmienić widok z sterta NT na własną stertę tak jak poprzednio.

Heap Selection

Korzystając z powyższego przykładu kodu z MemoryPool tworzeniem VSHeapTracker::CHeapTracker obiektu i naszą własną allocate metodą wywołującą AllocateEvent metodę, można teraz zobaczyć wynik tej niestandardowej alokacji, pokazując trzy wystąpienia w sumie 24 bajty, wszystkie typy Foo.

Domyślna sterta NT sterta wygląda tak samo jak wcześniej, z dodatkiem naszego CHeapTracker obiektu.

NT Heap with Tracker

Podobnie jak w przypadku standardowego sterta systemu Windows, można również użyć tego narzędzia do porównywania migawek i wyszukiwania przecieków i uszkodzeń w niestandardowej stercie, która została opisana w głównej dokumentacji użycia pamięci.

Napiwek

Program Visual Studio zawiera również narzędzie Użycie pamięci w zestawie narzędzi profilowania wydajności, które jest włączone w opcji menu Debug Performance>Profiler lub kombinacji klawiatury Alt+F2. Ta funkcja nie obejmuje śledzenia stert i nie będzie wyświetlać niestandardowej sterty zgodnie z opisem w tym miejscu. To funkcje zawiera tylko okno Narzędzia diagnostyczne, które można włączyć za pomocą menu Debugowanie>narzędzi diagnostycznych Pokaż>okna lub kombinację klawiatury Ctrl+Alt+F2.