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ę:
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++.
Dołącz nagłówek niestandardowego dostawcy ETW sterty:
#include <VSCustomNativeHeapEtwProvider.h>
__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ącyS_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 typB
, a nievoid
lubA
.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");
W przypadku przydzielania pamięci przy użyciu funkcji niestandardowej wywołaj
AllocateEvent
metodę (C++) lubVSHeapTrackerAllocateEvent
(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.W przypadku cofnięcia przydziału pamięci przy użyciu funkcji niestandardowej wywołaj
DeallocateEvent
funkcję (C++) lubVSHeapTracerDeallocateEvent
(C), przekazując wskaźnik do pamięci, aby śledzić cofanie przydziału:pHeapTracker->DeallocateEvent(memPtr);
or:
VSHeapTrackerDeallocateEvent(hHeapTracker, memPtr);
Podczas ponownego przydzielania pamięci przy użyciu funkcji niestandardowej wywołaj
ReallocateEvent
metodę (C++) lubVSHeapReallocateEvent
(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);
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 lubCloseHeapTracker
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.
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.
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.
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.