Eventos de heap de ETW nativos personalizados
O Visual Studio contém uma variedade de ferramentas de criação de perfil e diagnóstico, incluindo um criador de perfil de memória nativa. Esse criador de perfil vincula eventos ETW do provedor de heap e fornece uma análise de como a memória está sendo alocada e utilizada. Por padrão, essa ferramenta só pode analisar alocações feitas do heap padrão do Windows e todas as alocações fora desse heap nativo não serão exibidas.
Há vários casos em que você pode desejar usar seu próprio heap personalizado e evitar a sobrecarga de alocação do heap padrão. Por exemplo, você poderá usar VirtualAlloc para alocar uma grande quantidade de memória no início do aplicativo ou do jogo e depois gerenciar seus próprios blocos nessa lista. Nesse cenário, a ferramenta de criador de perfil de memória só verá essa alocação inicial e não o gerenciamento personalizado feito na parte de memória. No entanto, ao usar o Provedor ETW de Heap Nativo Personalizado, é possível informar a ferramenta sobre as alocações que estão sendo feitas fora do heap padrão.
Por exemplo, em um projeto como o seguinte, em que MemoryPool
é um heap personalizado, você verá apenas uma única alocação no heap do 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();
Um instantâneo da ferramenta Uso de Memória sem o acompanhamento de heap personalizado mostrará apenas a única alocação de byte 8192 e nenhuma das alocações personalizadas feitas pelo pool:
Ao realizar as etapas a seguir, podemos usar essa mesma ferramenta para acompanhar o uso de memória em nosso heap personalizado.
Como usar
Essa biblioteca pode ser usada no C e C++ com facilidade.
Inclua o cabeçalho do provedor ETW de heap personalizado:
#include <VSCustomNativeHeapEtwProvider.h>
Adicione o decorador
__declspec(allocator)
a qualquer função no gerenciador de heap personalizado que retorna um ponteiro para a memória de heap recém-alocada. Esse decorador permite que a ferramenta identifique corretamente o tipo da memória que está sendo retornado. Por exemplo:__declspec(allocator) void *MyMalloc(size_t size);
Observação
Esse decorador informará o compilador que essa função é uma chamada a um alocador. Cada chamada à função gerará o endereço do site da chamada, o tamanho da instrução de chamada e a typeId do novo objeto para um novo símbolo
S_HEAPALLOCSITE
. Quando uma pilha de chamadas for alocada, o Windows emitirá um evento ETW com essas informações. A ferramenta de criador de perfil de memória percorre a pilha de chamadas em busca de uma correspondência de endereço de retorno com um símboloS_HEAPALLOCSITE
e as informações de typeId no símbolo são usadas para exibir o tipo de runtime da alocação.Em resumo, isso significa que uma chamada parecida com
(B*)(A*)MyMalloc(sizeof(B))
será mostrada na ferramenta como sendo do tipoB
, nãovoid
nemA
.Para o C++, crie o objeto
VSHeapTracker::CHeapTracker
, fornecendo um nome para o heap, que será mostrado na ferramenta de criação de perfil:auto pHeapTracker = std::make_unique<VSHeapTracker::CHeapTracker>("MyCustomHeap");
Se você estiver usando o C, use a função
OpenHeapTracker
. Essa função retornará um identificador que será usado ao chamar outras funções de acompanhamento:VSHeapTrackerHandle hHeapTracker = OpenHeapTracker("MyHeap");
Ao alocar a memória usando a função personalizada, chame o método
AllocateEvent
(C++) ouVSHeapTrackerAllocateEvent
(C), passando o ponteiro para a memória e seu tamanho, para acompanhar a alocação:pHeapTracker->AllocateEvent(memPtr, size);
ou
VSHeapTrackerAllocateEvent(hHeapTracker, memPtr, size);
Importante
Não se esqueça de marcar a função de alocador personalizada com o decorador
__declspec(allocator)
descrito anteriormente.Ao desalocar a memória usando a função personalizada, chame a função
DeallocateEvent
(C++) ouVSHeapTracerDeallocateEvent
(C), passando o ponteiro para a memória, para acompanhar a desalocação:pHeapTracker->DeallocateEvent(memPtr);
ou:
VSHeapTrackerDeallocateEvent(hHeapTracker, memPtr);
Ao realocar a memória usando a função personalizada, chame o método
ReallocateEvent
(C++) ouVSHeapReallocateEvent
(C), passando um ponteiro para a nova memória, o tamanho da alocação e um ponteiro para a memória antiga:pHeapTracker->ReallocateEvent(memPtrNew, size, memPtrOld);
ou:
VSHeapTrackerReallocateEvent(hHeapTracker, memPtrNew, size, memPtrOld);
Por fim, para fechar e limpar o controlador de heap personalizado no C++, use o destruidor
CHeapTracker
, manualmente ou por meio de regras de escopo padrão ou a funçãoCloseHeapTracker
no C:delete pHeapTracker;
ou:
CloseHeapTracker(hHeapTracker);
Acompanhar o uso de memória
Com essas chamadas implementadas, o uso de heap personalizado agora pode ser acompanhado usando a ferramenta padrão Uso de Memória no Visual Studio. Para obter mais informações sobre como usar essa ferramenta, consulte a documentação Uso de memória. Verifique se você habilitou a de criação de perfil de heap com instantâneos; caso contrário, você não verá o uso de heap personalizado exibido.
Para exibir o acompanhamento de heap personalizado, use o menu suspenso Heap localizado no canto superior direito da janela Instantâneo para alterar a exibição de Heap NT para seu próprio heap nomeado anteriormente.
Usando o exemplo de código acima, com MemoryPool
criando um objeto VSHeapTracker::CHeapTracker
e nosso próprio método allocate
agora chamando o método AllocateEvent
, agora é possível ver o resultado da alocação personalizada, mostrando três instâncias que totalizam 24 bytes, todos do tipo Foo
.
O heap padrão Heap NT tem a mesma aparência que anteriormente, com a adição de nosso objeto CHeapTracker
.
Assim como ocorre com o heap padrão do Windows, também é possível usar essa ferramenta para comparar instantâneos e procurar perdas e danos no heap personalizado, que é descrito na documentação principal Uso de memória.
Dica
O Visual Studio também contém uma ferramenta Uso de Memória no conjunto de ferramentas Criação de Perfil de Desempenho, que é habilitada na opção de menu Depurar>Criador de Perfil de Desempenho ou na combinação de teclas Alt+F2. Esse recurso não inclui o acompanhamento de heap e não exibirá o heap personalizado descrito aqui. Somente a janela Ferramentas de Diagnóstico, que pode ser habilitada com o menu Depurar>Windows>Mostrar Ferramentas de Diagnóstico ou a combinação de teclas Ctrl+Alt+F2, contém essa funcionalidade.
Conteúdo relacionado
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de