Medir o uso de memória no Visual Studio (C#, Visual Basic, C++, F#)

Encontre vazamentos de memória e memória ineficiente enquanto estiver depurando com a ferramenta de diagnóstico Uso de Memória integrada ao depurador. A ferramenta Uso de Memória permite que você obtenha um ou mais instantâneos do heap de memória gerenciada e do heap de memória nativa para entender o impacto do uso de memória dos tipos de objeto. Você também pode analisar o uso de memória sem um depurador anexado ou definindo como destino um aplicativo em execução. Para obter mais informações, confira Executar ferramentas de criação de perfil com ou sem o depurador. Para obter informações sobre como escolher a melhor ferramenta de análise de memória para suas necessidades, consulte Escolher uma ferramenta de análise de memória.

Embora você possa coletar instantâneos de memória a qualquer momento na ferramenta Uso de Memória, pode usar o depurador do Visual Studio para controlar como o seu aplicativo é executado ao investigar problemas de desempenho. A definição de pontos de interrupção, passo a passo, Interromper Tudo e outras ações de depurador podem ajudá-lo a concentrar as investigações de desempenho nos caminhos de código mais relevantes. A execução dessas ações enquanto o aplicativo é executado pode eliminar o ruído do código que não lhe interessa e reduzir significativamente a quantidade de tempo necessário para diagnosticar um problema.

Importante

As Ferramentas de Diagnóstico integradas ao depurador têm suporte para desenvolvimento de .NET no Visual Studio, incluindo aplicativos ASP.NET, ASP.NET Core, de desenvolvimento nativo/C++ e de modo misto (.NET e nativo). O Windows 8 ou posterior é necessário para executar ferramentas de criação de perfil com o depurador (janela Ferramentas de Diagnóstico).

Neste tutorial, você irá:

  • Tirar instantâneos da memória
  • Analisar dados de uso de memória

Se Uso de Memória não fornece os dados necessários, outras ferramentas de criação de perfil no Criador de Perfil de Desempenho fornecem diferentes tipos de informações que poderão ser úteis. Em muitos casos, o gargalo de desempenho do aplicativo pode ser causado por algo que não seja a memória, como a CPU, a interface do usuário de renderização ou o tempo de solicitação de rede.

Observação

Suporte para alocador personalizado O criador de perfil de memória nativa funciona coletando dados de evento ETW de alocação emitidos durante o tempo de execução. Os alocadores no CRT e no SDK do Windows foram anotados no nível de origem para que seus dados de alocação possam ser capturados. Se você estiver escrevendo seus próprios alocadores, todas as funções que retornarem um ponteiro para uma memória heap recém-alocada poderão ser decoradas com __declspec(allocator), como visto neste exemplo de myMalloc:

__declspec(allocator) void* myMalloc(size_t size)

Coletar dados de uso de memória

  1. Abra o projeto que deseja depurar no Visual Studio e defina um ponto de interrupção no aplicativo no ponto em que deseja começar a examinar o uso da memória.

    Se houver uma área em que você suspeite de um problema de memória, defina o primeiro ponto de interrupção antes que ocorra o problema de memória.

    Dica

    Como pode ser um desafio capturar o perfil de memória de uma operação de seu interesse quando o aplicativo aloca e desaloca memória com frequência, defina pontos de interrupção no início e no final da operação (ou percorra a operação) para localizar o ponto exato em que a memória foi alterada.

  2. Defina um segundo ponto de interrupção ao fim da função ou região de código que você deseja analisar (ou após a ocorrência de um problema de memória suspeito).

  3. A janela Ferramentas de Diagnóstico é exibida automaticamente, a menos que tenha sido desativada. Para abrir a janela novamente, clique em Depurar>Windows>Mostrar Ferramentas de Diagnóstico.

  4. Escolha Uso de Memória com a configuração Selecionar Ferramentas na barra de ferramentas.

    Screenshot of Diagnostics Tools.

    Screenshot of Diagnostics Tools.

  5. Clique em Depurar/Iniciar Depuração (ou em Iniciar na barra de ferramentas ou em F5).

    Quando o aplicativo terminar de ser carregado, a exibição Resumo das Ferramentas de Diagnóstico será exibida.

    Screenshot of Diagnostics Tools Summary Tab.

    Observação

    Como a coleta de dados de memória pode afetar o desempenho de depuração de seus aplicativos mistos ou nativos, os instantâneos de memória são desabilitados por padrão. Para habilitar instantâneos de aplicativos mistos ou nativos, inicie uma sessão de depuração (Tecla de atalho: F5). Quando a janela Ferramentas de Diagnóstico for exibida, escolha a guia Uso de Memória e, em seguida, Criação de Perfil de Heap.

    Screenshot of Enable snapshots.

    Pare (tecla de atalho: Shift+F5) e reinicie a depuração.

    Screenshot of Diagnostics Tools Summary Tab.

    Observação

    Como a coleta de dados de memória pode afetar o desempenho de depuração de seus aplicativos mistos ou nativos, os instantâneos de memória são desabilitados por padrão. Para habilitar instantâneos de aplicativos mistos ou nativos, inicie uma sessão de depuração (Tecla de atalho: F5). Quando a janela Ferramentas de Diagnóstico for exibida, escolha a guia Uso de Memória e, em seguida, Criação de Perfil de Heap.

    Screenshot of Enable snapshots.

    Pare (tecla de atalho: Shift+F5) e reinicie a depuração.

  6. Para obter um instantâneo no início da sessão de depuração, escolha Tirar instantâneo na barra de ferramentas de resumo Uso de Memória. (Talvez seja útil definir um ponto de interrupção aqui também.)

    Screenshot of Take Snapshot button.

    Screenshot of Take Snapshot button.

    Dica

    Para criar uma linha de base para comparações de memória, tire um instantâneo no início da sessão de depuração.

  7. Execute o cenário que fará com que o primeiro ponto de interrupção seja atingido.

  8. Enquanto o depurador estiver pausado no primeiro ponto de interrupção, escolha Tirar instantâneo na barra de ferramentas de resumo Uso de Memória.

  9. Pressione F5 para executar o aplicativo até o segundo ponto de interrupção.

  10. Agora, crie outro instantâneo.

    Neste ponto, você pode começar a analisar os dados.

    Se você tiver problemas para coletar ou exibir dados, confira Solucionar erros de criação de perfil e corrigir problemas.

Analisar dados de uso de memória

As linhas da tabela de resumo de Uso de Memória listam os instantâneos obtidos durante a sessão de depuração e fornecem links para exibições mais detalhadas.

Screenshot of Memory Usage table.

Screenshot of Memory Usage table.

O nome da coluna depende do modo de depuração que você escolher nas propriedades do projeto: .NET, nativo ou misto (tanto .NET quanto nativo).

  • As colunas Objetos (Diff) e Alocações (Diff) exibem o número de objetos no .NET e na memória nativa quando o instantâneo foi criado.

  • A coluna Tamanho do Heap (Diff) exibe o número de bytes no .NET e heaps nativos

Quando você tira vários instantâneos, as células da tabela de resumo incluem a alteração no valor entre o instantâneo de linha e o instantâneo anterior.

Para analisar o uso da memória, clique em um dos links que abre um relatório detalhado do uso de memória:

  • Para exibir detalhes da diferença entre o instantâneo atual e o anterior, escolha o link de alteração à esquerda da seta (Memory Usage Increase). Uma seta vermelha indica um aumento no uso de memória e uma verde indica uma redução.

Dica

Para ajudar a identificar problemas de memória mais rapidamente, os relatórios de comparação são classificados pelos tipos de objeto que mais aumentaram no número geral (clique no link de alteração na coluna Objetos (Comparação)) ou que mais aumentaram quanto ao tamanho geral do heap (clique no link de alteração na coluna Tamanho do Heap (Comparação)).

  • Para exibir detalhes apenas do instantâneo selecionado, clique no link que não é de alteração.

    O relatório é exibido em uma janela separada.

Relatórios de tipos gerenciados

Escolha o link atual de uma célula Objetos (Comparação) ou Alocações (Comparação) da tabela de resumo de Uso de Memória.

Screenshot of managed type report.

Screenshot of managed type report.

O painel superior mostra a contagem e o tamanho dos tipos no instantâneo, incluindo o tamanho de todos os objetos referenciados pelo tipo (inclusive tamanho).

A árvore Caminhos para a Raiz no painel inferior exibe os objetos que referenciam o tipo selecionado no painel superior. O coletor de lixo do .NET limpa a memória de um objeto apenas quando o último tipo que faz referência a ele é liberado.

A árvore Tipos Referenciados exibe as referências mantidas pelo tipo selecionado no painel superior.

Screenshot of Referenced Objects report.

A árvore Tipos Referenciados exibe as referências mantidas pelo tipo selecionado no painel superior.

Screenshot of Referenced Objects report.

Para exibir as instâncias de um tipo selecionado no painel superior, clique em "Exibir Instâncias" ao lado do tipo de objeto.

Screenshot of the Instances view in the Memory Usage tool.

Screenshot of the Instances view in the Memory Usage tool.

O modo de exibição Instâncias exibe as instâncias do objeto selecionado no instantâneo no painel superior. O painel Caminhos para Raiz e Objetos Referenciados exibe os objetos que referenciam a instância selecionada e os tipos de que a instância selecionada referencia. Quando o depurador é interrompido no ponto em que o instantâneo foi tirado, você pode passar o mouse sobre a célula Valor para exibir os valores do objeto em uma dica de ferramenta.

Relatórios de tipo nativo

Escolha o link atual de uma célula Alocações (Comparação) ou Tamanho do Heap (Comparação) na tabela de resumo de Uso de Memória da janela Ferramentas de Diagnóstico.

Screenshot of Native Type View.

Screenshot of Native Type View.

O Modo de exibição de tipos exibe o número e tamanho dos tipos no instantâneo.

  • Escolha o ícone de instâncias (The instance icon in the Object Type column) de um tipo selecionado para exibir informações sobre os objetos do tipo selecionado no instantâneo.

    O modo de exibição Instâncias mostra cada instância do tipo selecionado. A seleção de uma instância exibe a pilha de chamadas resultou na criação da instância no painel Pilha de Chamadas de Alocação.

    Screenshot of the Instances view and Allocation Call Stack pane.

  • Escolha Exibir Instâncias ao lado de um tipo selecionado para exibir informações sobre os objetos do tipo selecionado no instantâneo.

    O modo de exibição Instâncias mostra cada instância do tipo selecionado. A seleção de uma instância exibe a pilha de chamadas resultou na criação da instância no painel Pilha de Chamadas de Alocação.

    Screenshot of the Instances view and Allocation Call Stack pane.

  • Escolha Exibição de Pilhas na lista Exibir Modo para ver a pilha de alocação do tipo selecionado.

    Screenshot of Stacks view.

  • Escolha Pilhas para ver a pilha de alocação do tipo selecionado.

    Screenshot of Stacks view.

Insights de Uso da Memória

Para memória gerenciada, a ferramenta Análise de Memória também oferece vários insights automáticos integrados e avançados. Selecione a guia Insights nos relatórios de tipos gerenciados e ela mostrará os insights automáticos aplicáveis, como Strings duplicadas e Matrizes esparsas e Perdas do manipulador de eventos.

Screenshot of the insight view in the Memory Usage tool.

A seção Cadeias de caracteres duplicadas mostra a lista de cadeias de caracteres alocadas várias vezes no heap. Além disso, esta seção mostra o total de memória desperdiçada, ou seja, o (número de instâncias - 1) vezes o tamanho da cadeia de caracteres.

A seção Matrizes Esparsas mostra as matrizes preenchidas, em sua maioria, com zero elementos, o que pode ser ineficiente em termos de desempenho e uso de memória. A ferramenta de análise de memória detectará automaticamente essas matrizes e mostrará quanto de memória está sendo desperdiçada devido a esses valores zero.

A seção Perdas do manipulador de eventos, disponível no Visual Studio 2022 versão 17.9 Versão Prévia 1, mostra possíveis perdas de memória que podem ocorrer quando um objeto assina o evento de outro objeto. Se o editor do evento sobreviver ao assinante, o assinante permanecerá vivo, mesmo que não haja outras referências a ele. Isso pode levar a perdas de memória, em que a memória não utilizada não é liberada adequadamente, fazendo com que o aplicativo use cada vez mais memória ao longo do tempo.

Alguns tipos são conhecidos por terem campos que podem ser lidos para determinar o tamanho da memória nativa que estão mantendo. A guia Insights mostra os nós de memória nativos falsos no gráfico de objetos, que foram retidos por seus objetos pai, de modo que a interface do usuário os reconheça e exiba seu tamanho e gráfico de referência.

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

Relatórios de comparação (Diff)

  • Escolha o link de alteração em uma célula da tabela de resumo da guia Uso de Memória na janela Ferramentas de Diagnóstico.

    Screenshot of Choose a change link in a cell.

    Screenshot of Choose a change link in a cell.

  • Escolha um instantâneo na lista Comparar com de um relatório gerenciado ou nativo.

    Screenshot of Choose a snapshot from the Compare To list.

    Screenshot of Choose a snapshot from the Compare with list.

O relatório de comparação adiciona colunas (marcadas com (Diff)) ao relatório base que mostra a diferença entre o valor do instantâneo base e o do instantâneo de comparação. Veja como pode ser a aparência de um relatório de comparação Exibição de Tipo Nativo:

Screenshot of Native Types Diff View.

Screenshot of Native Types Diff View.

Blogs e vídeos

Analisar a CPU e a memória durante a depuração

Visual C++ Blog: Memory Profiling in Visual C++ 2015 (Blog do Visual C++: Criação de perfil de memória no Visual C++ 2015)

Próximas etapas

Neste tutorial, você aprendeu como coletar e analisar dados de uso da memória. Se você já concluiu o tour do criador de perfil, convém ler sobre uma abordagem geral para otimizar o código usando as ferramentas de criação de perfil.

Neste tutorial, você aprendeu a coletar e analisar dados de uso da memória durante a depuração. Talvez você queira saber mais sobre como analisar o uso de memória em builds de versão usando o Criador de Perfil de Desempenho.