Partilhar via


Utilitário de recolha e análise de capturas (dotnet-dump)

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

Nota

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

Instalar

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

  • Ferramenta global dotnet:

    Para instalar a versão mais recente do dotnet-dumppacote NuGet, use o comando `dotnet tool install`:

    dotnet tool install --global dotnet-dump
    
  • Download direto:

    Faça o download do executável da ferramenta que corresponde à sua plataforma:

    SO Plataforma
    Windows x86 | x64 | Braço | Arm-x64
    Aplicações Linux x64 | Braço | Arm64 | Musl-X64 | musl-Arm64

Nota

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 forma de recolher e analisar dumps no Windows, Linux e macOS sem envolver qualquer depurador nativo. Esta ferramenta é importante em plataformas como o Alpine Linux, onde um totalmente funcional lldb não está disponível. A dotnet-dump ferramenta permite que você execute comandos SOS para analisar falhas e o coletor de lixo (GC), mas não é um depurador nativo, portanto, coisas como exibir quadros de pilha nativos não são suportadas.

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 coletar
análise dotnet-dump
Dotnet-dump ps

dotnet-dump coletar

Captura um dump 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 coletar um dump.

  • -n|--name <name>

    Especifica o nome do processo do qual coletar um dump.

  • --type <Full|Heap|Mini>

    Especifica o tipo de dump, que determina os tipos de informações coletadas do processo. Existem três tipos:

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

    Se não for especificado, Full é o padrão.

  • -o|--output <output_dump_path>

    O caminho completo e o nome do arquivo onde 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 para o diretório especificado.

    Se não for especificado:

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

    AAAAMMDD é Ano/Mês/Dia e HHMMSS é Hora/Minuto/Segundo.

  • --diag

    Habilita o log de diagnóstico de coleta de dump.

  • --crashreport

    Permite a geração de relatórios de falhas.

Nota

No Linux e macOS, este comando espera que o aplicativo de destino e dotnet-dump compartilhe a mesma TMPDIR variável de ambiente. Caso contrário, o comando atingirá o tempo limite.

Nota

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

Nota

A coleta de um despejo completo ou de pilha pode fazer com que o sistema operacional tenha uma página de memória virtual substancial para o processo de destino. Se o processo de destino estiver sendo executado em um contêiner com um limite de memória imposto, o aumento do uso de memória pode fazer com que o sistema operacional encerre o contêiner se o limite for excedido. Recomendamos testar para garantir que o limite de memória esteja definido alto o suficiente. Outra opção é alterar ou remover temporariamente o limite antes da coleta de despejo, se seu ambiente oferecer suporte a isso.

análise dotnet-dump

Inicia um shell interativo para explorar um dump. 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>

    Executa o comando ao iniciar. Várias instâncias desse parâmetro podem ser usadas em uma invocação para comandos em cadeia. Os comandos serão executados na ordem em que são fornecidos na linha de comando. Se você quiser que o dotnet dump saia após os comandos, seu último comando deve ser 'exit'.

Analisar comandos SOS

Comando Função
analyzeoom Exibe as informações do último OOM que ocorreu em uma solicitação de alocação para o heap GC.
clrmodules Lista os módulos gerenciados no processo.
clrstack Fornece um rastreamento de pilha somente de 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 Ativa/desativa (-off) o registo SOS interno.
dso Exibe todos os objetos gerenciados encontrados 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áquinas de estado assíncronas na pilha coletada de lixo.
dumpassembly Exibe detalhes sobre uma montagem.
dumpclass Exibe informações sobre a estrutura EEClass no endereço especificado.
dumpconcurrentdictionary Exibe conteúdo de 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 em todos os AppDomains ou no especificado.
dumpgcdata Exibe informações sobre os dados GC.
dumpgen Exibe o conteúdo de pilha para a geração especificada.
dumpheap Exibe informações sobre a pilha coletada de lixo e estatísticas de coleta sobre objetos.
dumpil Exibe a linguagem intermediária comum (CIL) 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 MethodDesc no endereço especificado.
dumpmodule Exibe informações sobre o módulo no endereço especificado.
dumpmt Exibe informações sobre a tabela de método no endereço especificado.
dumpobj Exibe informações do objeto no endereço especificado.
dumpruntimetypes Localiza todos os objetos System.RuntimeType no heap GC e imprime o nome do tipo e MethodTable a que eles se referem também.
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 encontrados 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 tempo de execução internas.
eestack Executa dumpstack em todos os threads no processo.
eeversion Exibe informações sobre as versões de tempo de execução e SOS.
ehinfo Exibe os blocos de tratamento de exceção em um método JIT-ed.
exit ou quit Sai do modo interativo.
finalizequeue Exibe todos os objetos registrados para finalização.
findappdomain Tenta resolver o AppDomain de um objeto GC.
gchandles Exibe estatísticas sobre as alças 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) ao objeto no endereço especificado.
gcwhere Exibe o local no heap GC do endereço especificado.
histclear Libera todos os recursos usados pela família de comandos Hist.
histinit Inicializa as estruturas SOS a partir do log de estresse salvo no depurador.
histobj Examina todos os registros de realocação de log de estresse e exibe a cadeia de relocações de coleta de lixo que podem ter levado ao endereço 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 promoções e realocações da raiz especificada.
histstats Exibe estatísticas de log de estresse.
ip2md Exibe a MethodDesc estrutura no endereço especificado no código que foi compilado em JIT.
listnearobj Exibe o objeto que precede e sucede o endereço especificado.
logopen Habilita o registro em log de arquivos do console.
logclose Desabilita o log de arquivos do console.
logging Habilita/desabilita o registro interno de 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 Mostra a pilha de threads fundidos de forma semelhante ao painel 'Pilhas Paralelas' do Visual Studio.
pathto Exibe o caminho GC de <root> para <target>.
pe ou printexception Exibe e formata campos de qualquer objeto derivado da Exception classe no endereço especificado.
r ou registers Exibe os registros do thread.
runtimes Lista os tempos de execução no destino ou altera o tempo de execução padrão.
setclrpath Define o caminho para carregar arquivos coreclr dac/dbi usando setclrpath <path>o .
setsymbolserver Habilita o suporte ao servidor de símbolos.
sos Executa vários comandos de depuração coreclr. Use a sintaxe sos <command-name> <args>. Para obter mais informações, consulte '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 Task em um formato legível por humanos.
threadpool Exibe informações sobre o pool de threads de tempo de execução.
threadpoolqueue Exibe itens de trabalho do pool de threads enfileirados.
threadstate Pretty imprime o significado de um estado de threads.
threads <threadid> ou setthread <threadid> Define ou exibe o ID de thread atual para os comandos SOS.
timerinfo Exibe informações sobre temporizadores em execução.
token2ee Exibe a estrutura MethodTable e a estrutura MethodDesc para o token e o módulo especificados.
traverseheap Grava informações de pilha em um arquivo em um formato compreendido pelo CLR Profiler.
verifyheap Verifica a pilha GC em busca de sinais de corrupção.
verifyobj Verifica o objeto que é passado como um argumento para sinais de corrupção.

Nota

Detalhes adicionais podem ser encontrados em SOS Debugging Extension for .NET.

Dotnet-dump ps

Lista os processos dotnet dos quais os dumps podem ser coletados. dotnet-dump A versão 6.0.320703 e versões 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 dotnet-dump ps comando. A saída que você verá é a seguinte. Os argumentos de linha de comando, se houver, são mostrados na 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

Ao utilizar dotnet-dump

O primeiro passo é recolher um lixão. Esta etapa pode ser ignorada se um dump principal já tiver sido gerado. O sistema operativo ou a funcionalidade incorporada de geração de dump generation do sistema operativo ou do .NET Core runtime, podem criar dumps de núcleo.

$ 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 dump principal com o analyze comando:

$ 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.
>

Esta ação apresenta 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 não tratada 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 fugas de memória e alocações

Fugas de memória ocorrem quando a sua aplicação mantém referências a objetos que já não são necessários, impedindo o coletor de lixo de recuperar memória. Use dotnet-dump para identificar fugas de memória, encontrar os maiores objetos e perceber onde a memória está a ser consumida.

Para uma explicação completa da depuração de uma fuga de memória, veja Debug a memory leak em .NET.

Identificar os maiores objetos

Use o dumpheap comando com a -stat opção de ver um resumo dos objetos no heap, ordenados 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

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

Identificar objetos por namespace ou assembly

Para encontrar quais os módulos ou namespaces que consomem memória, use a -type opção com um nome parcial do tipo 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

Esta abordagem ajuda-o a identificar quais as partes da sua base de código responsáveis pelo consumo de memória.

Encontrar o maior número de instâncias

Para ver quais os tipos que têm mais instâncias, independentemente do tamanho total, consulte a coluna Count na dumpheap -stat saída. Objetos com um alto número de instâncias podem indicar problemas ineficientes de criação ou cache de objetos:

> 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 objetos com gcroot

Depois de identificar objetos grandes ou numerosos, use gcroot para perceber porque é que um objeto não está a ser recolhido no lixo. O gcroot comando mostra a cadeia de referência desde as raízes do GC até 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.

Esta saída mostra que o Customer objeto é mantido por um CustomerCache objeto, o que ajuda a identificar a origem da fuga no seu código.

Analisar a memória pelo tamanho do objeto

Use as -min opções e -max 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-o a focar-se nos maiores consumidores de memória.

Encontrar impasses

Uso dotnet-dump para diagnosticar situações de impasse onde os threads ficam bloqueados à espera de recursos. Para um walkthrough completo de depuração de deadlocks, veja Debug a deadlock em .NET.

Listar todos os tópicos

Use o threads comando para ver todos os threads geridos:

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

Analise as pilhas de fios

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

> clrstack -all

Procura padrões onde múltiplas threads estão bloqueadas em Monitor.Enter primitivas de sincronização ou similares.

Encontre donos de fechaduras

Use o syncblk comando para ver quais threads contêm bloqueios e quais estão à espera:

> 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 à espera do bloqueio. A coluna Informação de Thread Proprietário mostra qual thread é o proprietário do bloqueio.

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

Compare múltiplos dumps

Para compreender o crescimento da memória ao longo do tempo, recolha múltiplos dumps e compare-os:

  1. Recolha um dump de base: dotnet-dump collect -p <pid> -o baseline.dmp
  2. Deixe a sua aplicação correr e consumir mais memória.
  3. Recolhe um segundo dump: dotnet-dump collect -p <pid> -o after.dmp
  4. Analise ambos os dumps e compare os dumpheap -stat resultados.

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

Analisar memória para tipos específicos de objetos

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

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

Depois, 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

Recolha um depósito num contentor Docker

dotnet-dump requer ptrace capacidades no contentor. Uma forma comum de os conceder é começar o recipiente com --cap-add=SYS_PTRACE. Dependendo do ambiente, também podes precisar de ajustar o perfil de segurança do contentor. Consulte os Dumps: FAQ para ajuda no diagnóstico de problemas de configuração de segurança de contentores.

Para instalar dotnet-dump numa imagem de produção sem o SDK .NET, use os links download direto da secção Instalar, ou use uma build Docker multi-estágio para copiar os binários da ferramenta a partir de uma imagem SDK. Para orientações completas sobre diagnósticos de contentores, veja Recolher diagnósticos em contentores Linux.

Solução de problemas de coleta de despejo

A coleta de despejo requer que o processo possa chamar ptrace. Se você estiver enfrentando problemas para coletar dumps, o ambiente em que você está executando pode ser configurado para restringir essas chamadas. Consulte nossos Dumps: FAQ para obter dicas de solução de problemas e possíveis soluções para problemas comuns.

Consulte também