Compartilhar via


Utilitário de coleta e análise de despejo (dotnet-dump)

Este artigo se aplica a: ✔️ dotnet-dump versão 3.0.47001 e versões posteriores

Observação

dotnet-dump para macOS só tem suporte com versões .NET 5 e posteriores.

Instalar

Há duas maneiras de baixar e instalar o dotnet-dump:

Observação

Para usar dotnet-dump em um aplicativo x86, você precisa de uma versão x86 correspondente da ferramenta.

Sinopse

dotnet-dump [-h|--help] [--version] <command>

Descrição

A ferramenta global dotnet-dump é uma maneira de coletar e analisar despejos em Windows, Linux e macOS sem nenhum depurador nativo envolvido. Essa ferramenta é importante em plataformas como o Alpine Linux, em que um lldb totalmente funcional não está disponível. A ferramenta dotnet-dump permite que você execute comandos SOS para analisar falhas e o coletor de lixo (GC), mas não é um depurador nativo, portanto, não há suporte para itens como exibir quadros de pilha nativos.

Opções

  • --version

    Exibe a versão do utilitário dotnet-dump.

  • -h|--help

    Mostra a ajuda da linha de comando.

Comandos

Comando
dotnet-dump coleta
dotnet-dump analisar
dotnet-dump ps

dotnet-dump coleta

Captura um despejo de um processo.

Sinopse

dotnet-dump collect [-h|--help] [-p|--process-id] [-n|--name] [--type] [-o|--output] [--diag] [--crashreport]

Opções

  • -h|--help

    Mostra a ajuda da linha de comando.

  • -p|--process-id <PID>

    Especifica o número de ID do processo do qual um despejo será coletado.

  • -n|--name <name>

    Especifica o nome do processo do qual será coletado um despejo.

  • --type <Full|Heap|Mini>

    Especifica o tipo de despejo, que determina os tipos de informações são coletados do processo. Há três tipos:

    • Full - O maior despejo que contém toda a memória, incluindo as imagens do módulo.
    • Heap - Um despejo grande e relativamente abrangente que contém listas de módulos, listas de threads, todas as pilhas, informações de exceção, informações de manipulação e toda a memória, exceto imagens mapeadas.
    • Mini - Um pequeno despejo contendo listas de módulos, listas de threads, informações de exceção e todas as pilhas.
    • Triage - Um pequeno despejo contendo listas de módulos, listas de threads, informações de exceção, todas as pilhas e PII removidos.

    Se não for especificado, o padrão será Full.

  • -o|--output <output_dump_path>

    O caminho completo e o nome do arquivo em que o despejo coletado deve ser gravado. Verifique se o usuário sob o qual o processo dotnet está sendo executado tem permissões de gravação no diretório especificado.

    Se não especificado:

    • O padrão é .\dump_YYYYMMDD_HHMMSS.dmp no Windows.
    • O padrão é ./core_YYYYMMDD_HHMMSS no Linux e no macOS.

    YYYMMDD é ano/mês/dia e HHMMSS é hora/minuto/segundos.

  • --diag

    Habilita o log de diagnóstico da coleção de despejo.

  • --crashreport

    Habilita a geração de relatório de falha.

Observação

No Linux e no macOS, esse comando espera que o aplicativo de destino e dotnet-dump compartilhem a mesma variável de ambiente TMPDIR. Caso contrário, o comando terá um tempo limite.

Observação

Para coletar um despejo usando dotnet-dump, ele precisa ser executado como o mesmo usuário que o usuário que executa o processo de destino ou como raiz. Caso contrário, a ferramenta não estabelecerá uma conexão com o processo de destino.

Observação

A coleta de um despejo completo ou de heap pode fazer com que o sistema operacional seja páginado em memória virtual substancial para o processo de destino. Se o processo de destino estiver em execução em um contêiner com um limite de memória imposto, o aumento do uso da memória poderá fazer com que o sistema operacional encerre o contêiner se o limite for excedido. É recomendável testar para garantir que o limite de memória seja definido alto o suficiente. Outra opção é alterar ou remover temporariamente o limite antes da coleta de despejo se o ambiente der suporte a isso.

dotnet-dump analisar

Inicia um shell interativo para explorar um despejo. O shell aceita vários comandos SOS.

Sinopse

dotnet-dump analyze <dump_path> [-h|--help] [-c|--command]

Argumentos

  • <dump_path>

    Especifica o caminho para o arquivo de despejo a ser analisado.

Opções

  • -c|--command <debug_command>

    Executar o comando na inicialização. Várias instâncias desse parâmetro podem ser utilizadas em uma invocação para encadear comandos. Os comandos serão executados na ordem em que forem fornecidos na linha de comando. Se você deseja que o despejo do dotnet saia após os comandos, seu último comando deverá ser 'exit'.

Analisar comandos SOS

Comando Função
analyzeoom Exibe as informações do último OOM ocorrido em uma solicitação de alocação para o heap da GC.
clrmodules Lista os módulos gerenciados no processo.
clrstack Fornece um rastreamento de pilha apenas do código gerenciado.
clrthreads Lista os threads gerenciados que estão em execução.
clru Exibe uma desmontagem anotada de um método gerenciado.
d ou readmemory Despeja o conteúdo da memória.
dbgout Habilita/desabilita (-off) o log interno do SOS.
dso Exibe todos os objetos gerenciados encontradas dentro dos limites da pilha atual.
dumpalc Exibe detalhes sobre um AssemblyLoadContext colecionável para o qual o objeto especificado é carregado.
dumparray Exibe detalhes sobre uma matriz gerenciada.
dumpasync Exibe informações sobre máquina de estado assíncronas no heap com coleta de lixo.
dumpassembly Exibe detalhes sobre um assembly.
dumpclass Exibe informações sobre a estrutura de EEClass no endereço especificado.
dumpconcurrentdictionary Exibe o conteúdo do dicionário simultâneo.
dumpconcurrentqueue Exibe o conteúdo da fila simultânea.
dumpdelegate Exibe informações sobre um delegado.
dumpdomain Exibe informações sobre todos os assemblies dentro de todos os AppDomains ou o especificado.
dumpgcdata Exibe informações sobre os dados da GC.
dumpgen Exibe o conteúdo do heap para a geração especificada.
dumpheap Exibe informações sobre o heap com coleta de lixo e as estatísticas de coleção sobre objetos.
dumpil Exibe a CIL (linguagem intermediária comum) associada a um método gerenciado.
dumplog Grava o conteúdo de um log de estresse na memória no arquivo especificado.
dumpmd Exibe informações sobre a estrutura de MethodDesc no endereço especificado.
dumpmodule Exibe informações sobre o módulo no endereço especificado.
dumpmt Exibe informações sobre a tabela do método no endereço especificado.
dumpobj Exibe informações sobre o objeto no endereço especificado.
dumpruntimetypes Localiza todos os objetos System.RuntimeType no heap da GC e imprime o nome do tipo e MethodTable a que eles também se referem.
dumpsig Despeja a assinatura de um método ou campo especificado por <sigaddr> <moduleaddr>.
dumpsigelem Despeja um único elemento de um objeto de assinatura.
dumpstackobjects Exibe todos os objetos gerenciados encontradas dentro dos limites da pilha atual.
dumpvc Exibe informações sobre os campos de uma classe de valor.
eeheap Exibe informações sobre a memória de processo consumida por estruturas de dados de runtime internos.
eestack Executa dumpstack em todos os threads no processo.
eeversion Exibe informações sobre o runtime e as versões do SOS.
ehinfo Exibe os blocos de tratamento de exceções em um método com JIT.
exit ou quit Sai do modo interativo.
finalizequeue Exibe todos os objetos registrados para a finalização.
findappdomain Tenta resolver o AppDomain de um objeto GC.
gchandles Exibe estatísticas sobre identificadores do coletor de lixo no processo.
gcheapstat Exibe estatísticas sobre o coletor de lixo.
gcinfo Exibe a codificação JIT GC para um método.
gcroot Exibe informações sobre referências (ou raízes) para o objeto no endereço especificado.
gcwhere Exibe o local no heap de GC do endereço especificado.
histclear Libera qualquer recurso usado pela família de comandos Hist.
histinit Inicializa as estruturas de SOS com base no log de estresse salvo no elemento a ser depurado.
histobj Examina todos os registros de realocação do log de estresse e exibe a cadeia de realocações da coleta de lixo que podem ter levado o endereço a ser passado como um argumento.
histobjfind Exibe todas as entradas de log que fazem referência ao objeto no endereço especificado.
histroot Exibe informações relacionadas a ambas as promoções e realocações da raiz especificada.
histstats Exibe as estatísticas do log de estresse.
ip2md Exibe a estrutura MethodDesc no endereço especificado no código compilado com JIT.
listnearobj Exibe o objeto anterior e posterior ao endereço especificado.
logopen Habilita o registro em log do arquivo de console.
logclose Desabilita o registro em log do arquivo de console.
logging Habilita/desabilita o log interno do SOS.
lm ou modules Exibe os módulos nativos no processo.
name2ee Exibe as estruturas MethodTable e EEClass para o tipo ou método especificado no módulo especificado.
objsize Exibe o tamanho do objeto especificado.
parallelstacks Exibe a pilha de threads mesclados de forma semelhante ao painel Visual Studio 'Pilhas Paralelas'.
pathto Exibe o caminho do GC de <root> para <target>.
pe ou printexception Exibe e formata campos de qualquer objeto derivado da classe Exception no endereço especificado.
r ou registers Exibe os registros do thread.
runtimes Lista os runtimes no destino ou altera o runtime padrão.
setclrpath Define o caminho para carregar arquivos dac/dbi do coreclr usando setclrpath <path>.
setsymbolserver Habilita o suporte ao servidor de símbolos.
sos Executa vários comandos de depuração do coreclr. Use a sintaxe sos <command-name> <args>. Para obter mais informações, confira "soshelp".
soshelp ou help Exibe todos os comandos disponíveis.
soshelp <command> ou help <command> Exibe o comando especificado.
syncblk Exibe as informações do titular do SyncBlock.
taskstate Exibe um estado de tarefa em um formato legível por humanos.
threadpool Exibe informações sobre o pool de threads de runtime.
threadpoolqueue Exibe itens de trabalho do pool de threads enfileirados.
threadstate O pretty imprime o significado de um estado de threads.
threads <threadid> ou setthread <threadid> Define ou exibe a ID do thread atual para os comandos SOS.
timerinfo Exibe informações sobre a execução de temporizadores.
token2ee Exibe a estrutura MethodTable e a estrutura MethodDesc para o token e o módulo especificados.
traverseheap Grava informações do heap em um arquivo em um formato compreendido pelo do criador de perfil do CLR.
verifyheap Verifica se há sinais de corrupção no heap do GC.
verifyobj Verifica o objeto passado como um argumento em busca de sinais de corrupção.

Observação

Detalhes adicionais podem ser encontrados na Extensão de Depuração SOS para .NET.

dotnet-dump ps

Lista os processos de dotnet dos quais os despejos podem ser coletados. dotnet-dump versão 6.0.320703 e posteriores também exibem os argumentos de linha de comando com os quais cada processo foi iniciado, se disponível.

Sinopse

dotnet-dump ps [-h|--help]

Exemplo

Suponha que você inicie um aplicativo de longa execução usando o comando dotnet run --configuration Release. Em outra janela, você executa o comando dotnet-dump ps. A saída que você verá é a seguinte. Os argumentos de linha de comando, se houver, são mostrados no dotnet-dump versão 6.0.320703 e posterior.

> dotnet-dump ps

  21932 dotnet     C:\Program Files\dotnet\dotnet.exe   run --configuration Release
  36656 dotnet     C:\Program Files\dotnet\dotnet.exe

Usando dotnet-dump

A primeira etapa é coletar um despejo. Essa etapa poderá ser ignorada se um despejo de núcleo já tiver sido gerado. O sistema operacional ou o recurso interno de geração de dump do runtime do .NET Core podem criar despejos principais.

$ dotnet-dump collect --process-id 1902
Writing minidump to file ./core_20190226_135837
Written 98983936 bytes (24166 pages) to core file
Complete

Agora, analise o despejo de núcleo com o comando analyze:

$ dotnet-dump analyze ./core_20190226_135850
Loading core dump: ./core_20190226_135850
Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
Type 'quit' or 'exit' to exit the session.
>

Essa ação abre uma sessão interativa que aceita comandos como:

> clrstack
OS Thread Id: 0x573d (0)
    Child SP               IP Call Site
00007FFD28B42C58 00007fb22c1a8ed9 [HelperMethodFrame_PROTECTOBJ: 00007ffd28b42c58] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean, Boolean)
00007FFD28B42DD0 00007FB1B1334F67 System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo) [/root/coreclr/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs @ 472]
00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.Program.Foo4(System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54]
00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.Program.Foo2(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29]
00007FFD28B42F00 00007FB1B18D2F5A SymbolTestApp.Program.Foo1(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 24]
00007FFD28B42F30 00007FB1B18D168E SymbolTestApp.Program.Main(System.String[]) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 19]
00007FFD28B43210 00007fb22aa9cedf [GCFrame: 00007ffd28b43210]
00007FFD28B43610 00007fb22aa9cedf [GCFrame: 00007ffd28b43610]

Para ver uma exceção sem tratamento que matou seu aplicativo:

> pe -lines
Exception object: 00007fb18c038590
Exception type:   System.Reflection.TargetInvocationException
Message:          Exception has been thrown by the target of an invocation.
InnerException:   System.Exception, Use !PrintException 00007FB18C038368 to see more.
StackTrace (generated):
SP               IP               Function
00007FFD28B42DD0 0000000000000000 System.Private.CoreLib.dll!System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean, Boolean)
00007FFD28B42DD0 00007FB1B1334F67 System.Private.CoreLib.dll!System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)+0xa7 [/root/coreclr/src/mscorlib/src/System/Reflection/RuntimeMethodInfo.cs @ 472]
00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.dll!SymbolTestApp.Program.Foo4(System.String)+0x15d [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54]
00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.dll!SymbolTestApp.Program.Foo2(Int32, System.String)+0x34 [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29]
00007FFD28B42F00 00007FB1B18D2F5A SymbolTestApp.dll!SymbolTestApp.Program.Foo1(Int32, System.String)+0x3a [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 24]
00007FFD28B42F30 00007FB1B18D168E SymbolTestApp.dll!SymbolTestApp.Program.Main(System.String[])+0x6e [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 19]

StackTraceString: <none>
HResult: 80131604

Analisar vazamentos de memória e alocações

Os vazamentos de memória ocorrem quando seu aplicativo mantém referências a objetos que não são mais necessários, impedindo que o coletor de lixo recupere a memória. Use dotnet-dump para identificar vazamentos de memória, localizar os maiores objetos e entender onde a memória está sendo consumida.

Para obter um passo a passo completo da depuração de um vazamento de memória, consulte Depurar um vazamento de memória em .NET.

Identificar os maiores objetos

Use o dumpheap comando com a opção -stat para ver um resumo dos objetos no heap, classificado pelo tamanho total:

> dumpheap -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c1eeefba8      576        59904 System.Reflection.RuntimeMethodInfo
00007f6c1dc021c8     1749        95696 System.SByte[]
00000000008c9db0     3847       116080      Free
00007f6c1e784a18      175       128640 System.Char[]
00007f6c1dbf5510      217       133504 System.Object[]
00007f6c1dc014c0      467       416464 System.Byte[]
00007f6c21625038        6      4063376 testwebapi.Controllers.Customer[]
00007f6c20a67498   200000      4800000 testwebapi.Controllers.Customer
00007f6c1dc00f90   206770     19494060 System.String
Total 428516 objects

Essa saída mostra quais tipos consomem mais memória. Neste exemplo, System.String os objetos consomem cerca de 19 MB e Customer os objetos consomem cerca de 4,8 MB.

Identificar objetos por namespace ou assembly

Para localizar quais módulos ou namespaces estão consumindo memória, use a opção -type com um nome de tipo parcial para filtrar os resultados:

> dumpheap -type MyCompany.Data -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c21625038    15000      3600000 MyCompany.Data.CustomerRecord
00007f6c21625040     8000      2560000 MyCompany.Data.OrderHistory
00007f6c21625048     2000       960000 MyCompany.Data.ProductCache
Total 25000 objects, 7120000 bytes

Essa abordagem ajuda você a identificar quais partes da base de código são responsáveis pelo consumo de memória.

Localizar o maior número de instanciações

Para ver quais tipos têm mais instâncias, independentemente do tamanho total, examine a coluna Contagem na dumpheap -stat saída. Objetos com contagens de instâncias altas podem indicar problemas de criação ou cache de objetos ineficientes:

> dumpheap -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c1dc00f90   206770     19494060 System.String
00007f6c20a67498   200000      4800000 testwebapi.Controllers.Customer
00007f6c1dc021c8     1749        95696 System.SByte[]

Este exemplo mostra 206.770 String instâncias e 200.000 Customer instâncias.

Analisar referências de objeto com gcroot

Depois de identificar objetos grandes ou numerosos, use gcroot para descobrir por que um objeto não está sendo coletado. O gcroot comando mostra a cadeia de referência das raízes do GC para um objeto específico:

> dumpheap -mt 00007f6c20a67498
         Address               MT     Size
00007f6ad09421f8 00007f6c20a67498       24
...

> gcroot 00007f6ad09421f8

Thread 3f68:
    00007F6795BB58A0 00007F6C1D7D0745 testwebapi.Controllers.CustomerCache.GetAll()
        rbx:  (interior)
            ->  00007F6BDFFFF038 System.Object[]
            ->  00007F69D0033570 testwebapi.Controllers.Processor
            ->  00007F69D0033588 testwebapi.Controllers.CustomerCache
            ->  00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer]]
            ->  00007F6C000148A0 testwebapi.Controllers.Customer[]
            ->  00007F6AD0942258 testwebapi.Controllers.Customer

Found 1 root.

Essa saída mostra que o Customer objeto é mantido por um CustomerCache objeto, o que ajuda a identificar a origem do vazamento em seu código.

Analisar a memória por tamanho do objeto

Use as -min opções e -max as opções para filtrar objetos por tamanho:

> dumpheap -min 100000 -stat

Statistics:
              MT    Count    TotalSize Class Name
00007f6c21625038        6      4063376 testwebapi.Controllers.Customer[]
00007f6c1dc014c0       12       416464 System.Byte[]
Total 18 objects

Este comando mostra apenas objetos maiores que 100.000 bytes, ajudando você a se concentrar nos maiores consumidores de memória.

Localizar deadlocks

Use dotnet-dump para diagnosticar situações de deadlock em que os threads são bloqueados aguardando recursos. Para obter um passo a passo completo de depuração de deadlock, consulte Depurar um deadlock no .NET.

Listar todos os threads

Use o threads comando para ver todos os threads gerenciados:

> threads
*0 0x1DBFF (121855)
 1 0x1DC01 (121857)
 2 0x1DC02 (121858)
 ...

Examinar pilhas de thread

Use clrstack -all para ver as pilhas de chamadas de todos os threads:

> clrstack -all

Procure padrões em que vários threads são bloqueados ou Monitor.Enter primitivos de sincronização semelhantes.

Localizar proprietários de bloqueio

Use o syncblk comando para ver quais threads mantêm bloqueios e quais threads estão aguardando:

> syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
   43 00000246E51268B8          603         1 0000024B713F4E30 5634  28   00000249654b14c0 System.Object
   44 00000246E5126908            3         1 0000024B713F47E0 51d4  29   00000249654b14d8 System.Object

A coluna MonitorHeld mostra o número de threads aguardando o bloqueio. A coluna Informações do Thread Proprietário mostra qual thread possui o bloqueio.

Cenários avançados de análise de memória

Comparar vários despejos

Para entender o crescimento da memória ao longo do tempo, colete vários despejos e compare-os:

  1. Coletar um despejo de linha de base: dotnet-dump collect -p <pid> -o baseline.dmp
  2. Permitir que seu aplicativo seja executado e consuma mais memória.
  3. Coletar um segundo despejo: dotnet-dump collect -p <pid> -o after.dmp
  4. Analise os despejos e compare os dumpheap -stat resultados.

Procure tipos que tenham significativamente mais instâncias ou tamanhos totais maiores no segundo despejo.

Analisar memória para tipos de objeto específicos

Para despejar todas as instâncias de um tipo específico:

> dumpheap -type Customer
         Address               MT     Size
00007f6ad09421f8 00007f6c20a67498       24
00007f6ad0942210 00007f6c20a67498       24
...

Em seguida, use dumpobj para examinar objetos individuais:

> dumpobj 00007f6ad09421f8
Name:        testwebapi.Controllers.Customer
MethodTable: 00007f6c20a67498
EEClass:     00007f6c21625000
Size:        24(0x18) bytes
File:        /app/testwebapi.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007f6c1dc00f90  4000001        8        System.String  0 instance 00007f6ad09421f0 Name
00007f6c1dbf4c18  4000002       10         System.Int32  1 instance               42 Id

Coletar um despejo em um contêiner do Docker

dotnet-dump requer ptrace recursos no contêiner. Uma maneira comum de concedê-los é iniciar o contêiner com --cap-add=SYS_PTRACE. Dependendo do seu ambiente, talvez você também precise ajustar o perfil seccomp do contêiner. Confira os despejos: perguntas frequentes sobre como ajudar a diagnosticar problemas de configuração de segurança de contêiner.

Para instalar dotnet-dump em uma imagem de produção sem o SDK do .NET, use os links de download direct download da seção Instalar ou use um build do Docker multi-stage para copiar os binários da ferramenta de uma imagem do SDK. Para obter diretrizes completas de diagnóstico de contêiner, consulte Coletar diagnósticos em contêineres do Linux.

Solução de problemas de coleta de despejo

A coleta de despejo requer que o processo seja capaz de chamar ptrace. Se você estiver enfrentando problemas ao coletar despejos, o ambiente em que você está executando poderá estar configurado para restringir essas chamadas. Confira Despejos: perguntas frequentes para obter dicas de solução de problemas e possíveis soluções para problemas comuns.

Confira também