Debug Profundo

Descobrindo a causa Raiz dos problemas com Dumps de memória

Wilson Santos
7 min readJan 10, 2021

Existem muitas situações que não podemos “debugar” o código de uma aplicação em produção, podemos não ter o código fonte por exemplo, ou mesmo pode ser um ambiente inacessível.

Você já pensou que na verdade toda aplicação está na memória do computador não exatamente o código fonte, mas as instruções, se pudéssemos ver a memória do computador poderíamos fazer uma análise do problema em um nível bem mais baixo observando quanta memória estamos usando, quais áreas da memória estão sendo alocadas, quantas threads existem, o que está esperando o que, como foi o comportamento do coletor de lixo essa análise pode ser feita com um aplicativo chamado Windbg.

winDgbPreview melhorzinho que seu antecessor windbg

A análise de Dumps de memória nos coloca em contato com uma realidade esquecida por programadores modernos, uma realidade ligada ao conhecimento básico de computação e arquitetura de computadores e sistemas operacionais.

Além disso é muito importante entender um pouco da infraestrutura da sua linguagem e seu Framework, precisamos entender se ela é gerenciada, como ela gerencia memória , entender de computação básica como os espaços HEAP e Stack funciona.

Um dos principais aplicativos utilizado para fazer esse trabalho é o Windbg

Windbg Resumo

  1. Windbg é um software que analisa a memória, podemos usar o WindbgPreview da loja Ms.
  2. o Windbg pode analisar um arquivo com o conteúdo da memória, um Dump, ou um .exe vivo.
  3. Esse Aplicativo mostra tudo que está na memória inclusive dados sensíveis como senhas de acesso. etc. E através de extensões e comandos específico passado na GUI do software vamos fazendo a análise de acordo com o cenário do problema.
  4. Os cenários mais comuns são Alta Demanda de processamento, Memory Leak ou situações para encontrar erros e Exceptions.
  5. Os dados presentes na memória são basicamente endereços Hexadecimais e registradores, para que possamos correlacionar esses dados com nosso código precisamos carregar os símbolos do código que estamos analisando
  6. no .net os símbolos são armazenados no *.pdb.
  7. Além dos símbolos do seu código existem símbolos da infraestrutura, e dos frameworks .net core e sistema operacional.
  8. Existem problemas de Compatibilidade entre as plataformas da aplicação 32 bits e 64 bits, Dumps devem seguir a Arquitetura do sistema.
  9. Existem diversas formas de gerar um DUMP de memória sendo pelo ProcDump, DebugDiag, AdPlus ou Process Explorer e no Azure podemos usa o KUDU
  10. O básico para fazer uma análise descente do DUMP é conhecer a plataforma
  11. Podemos publicar um PDB junto da aplicação, pois não temos impacto na performance nem mesmo em segurança, isso é um mito comum
  12. Falando de DEVOPS pulicar o PDB em um Simbols Server é uma boa prática pois podemos diminuir o tempo de deploy
  13. O Fato de publicar em Debug sim torna a aplicação mais lenta, pois uma série de otimizações vão deixar de ser feitas pelo JIT

Vamos gerar nosso primeiro Dump usando o DebugDiag

  1. Abra o DebugDiag Collection
  2. Selecione o Botão Add Rule
  3. Escolha o Tipo da Regra por exemplo Crash (pegar Exception)
  4. Na próxima telinha escolha como você vai filtrar os processos, por exemplo A Specific NT Service
  5. Caso tenha escolhido a opção acima escolha o serviço
  6. Agora Clicamos em Advanced Settings Botão Exceptions
  7. Adicionamos uma exception
  8. No caos de uma aplicação .net vamos escolher CLR Exception
  9. No Dropdown ActionType Escolha Full User dump
  10. Action Limit deixa 1
  11. Na tela anterior na caixa de Unconfigured First Change Exception escolha Full User Dump no action Type e 1 para o Action Limit
  12. Pronto basta avançar até o Final e definir onde o arquivo vai ser gerado

Vamos gerar nosso primeiro Dump usando o procdump

Trigger de CPU 20% por mais de 5 segundos gerar dump full

procdump -ma -c 20 -s 5 <processId|processName>

Trigger de exception, gerar dump full

procdump -ma -e -f InvaliOperationException  <processId|processName>

Coletar 3 Dumps em 3 min

procdump -ma -n 3 -s 180 PID

Uma outra coisa bacana é usar o comando abaixo para pegar qual exception esta acontecendo e depois filtrar a geração do Dump com ela.

Monitora uma aplicação para pegar uma possível exception

procdump -e 1 -f "" pid ou pname

Existem várias configurações que podemos fazer no Windbg antes de começar a analisar Bibliotecas com SOS e MEX são uma boa pedida.

Mex

A extensão de depuração MEX para Windbg pode ajudá-lo a simplificar tarefas comuns do depurador e fornece recursos poderosos de filtragem de texto para o depurador

Carregar mex

.load mex

Listar exceptions

!dae

SOS

A Extensão de Depuração SOS (SOS.dll) ajuda a depurar programas gerenciados no Visual Studio e no depurador do Windows (Windbg.exe) fornecendo informações sobre o ambiente interno do CLR (Common Language Runtime). Essa ferramenta exige que o projeto tenha depuração não gerenciada habilitada. SOS.dll é instalado automaticamente com .NET Framework

Essa dll vem junto com o deploy quando compilamos a aplicação Self container no diretório win10x64

dotnet publish --runtime

Gerar Dump do AppService da sua Aplicação Azure.

Acesse o KUDU do seu appService, no menu process Explorer você pode clicar com botão direito no item da lista e baixar um Dump Full ou um mini Dump;

O arquivo de dump normalmente é muito grande e essa ferramenta disponibiliza o dump via download e isso nem sempre funciona, uma outra opção para baixar os dumps é o crashdiag que pode ser instalado pelo portal do Azure no KUDU.

Lista de Comandos do Windbg

  1. peb: Mais informações sobre o processo (threads, stacks, locals, Enviroments Variables)
  2. runaway: Quem está rodadndo, vai mostrar as threads e podemos navegar entre as threads usando ~<numero da therad> s
  3. dv: Mostrar valores das variáveis.
  4. cordll -T coreclr.dll -N -ve Tem que fazer mesmo com Erro
  5. verifyheap: verificar se sua memória está ok
  6. ~<numero da therad> s: Trocar de thread
  7. clrstack: stack do .net
  8. IP2MD [hexadecimal da memória]: mostra as definições de meta dados, ou seja, o nome do método
  9. dumpil [hexadecimal da memória]
  10. dumpstack -EE: Verificar a stack
  11. clrstack -a: Verificar a stack e mostra os valores das variáveis em hexadecimal
  12. EEVersion: traz dados do GC e do framework
  13. EEHeap — gc: o que tem na heap nesse momento
  14. Dumpheap -stat: ele vai olhar para todos os objetos da memória e vai mostrar o tamanho deles em ordem.
  15. gcroot [hexadecimal]: quem é o dono desse objeto, quem está impedindo esse cara de ser coletado.
  16. lastevent: normalmente não funciona para o .net, mas é ima tentativa em situações de crash
  17. dso: lista conjunto de elementos do stack

Analise Memory Leak .net core Windbg

  1. Carregar o SSO
  2. Verificar a heap (verifyheap)
  3. Verificar a memória gerenciadas
  4. Verificar o tamanho dos objetos me memória (Dumpheap -stat)
  5. Filtrar a lista de objetos dessa lista acima
  6. Analisar o conteúdo dos objetos

DebugDiag Analysis

https://www.microsoft.com/en-us/download/details.aspx?id=58210

Ele vai fornecer um relatório em HTML com uma série de dados, referentes a Erros, memória Heap e Stack Threads e muito mais.

Outra coisa bacana que pude ver na maior parte dos materiais sobre análise de dumps de memória e a oportunidade de entender como as coisas funcionam por baixo do campo do .net, por exemplo você sabia que se criar uma lista assim que vai receber 100 itens

var lista = new List<int>();

é menos eficiente do que criar assim

var lista = new List<int>(1000)

Você sabia que o .net trabalha com o conceito de string imutável, sabe qual a relação disso com a heap e com a stack?

Aqui tem alguns artigos que podem complementar esses conteúdos.

  1. Heap Stack
  2. Span

Referencias

  1. https://docs.microsoft.com/pt-br/dotnet/framework/tools/sos-dll-sos-debugging-extension
  2. https://www.microsoft.com/en-us/download/details.aspx?id=53304
  3. https://learn.microsoft.com/en-us/sysinternals/downloads/procdump
  4. Talk Coders — Analisando Dumps de Memória de Aplicações .NET
  5. Analisando dumps de memória de aplicações .NET
  6. Performance máxima em .NET: como entender o GC pode acelerar apps em 10x
  7. C# AVANÇADO — Gerenciamento de memória
  8. Utilizando IntelliTrace para debugar suas aplicações | Using Intellitrace for application debug
  9. Gerenciamento de Memória (Parte 1) | Entendendo Back-end para Iniciantes (Parte 5)
  10. Hunting .NET memory leaks with Windbg
  11. Buscando performance em .NET? Te ajudo a dar os primeiros passos para entender IL, JIT, WinDBG e Assembly
  12. Coletando e analisando dump com o .NET

--

--

Wilson Santos

Nos últimos 15 anos, venho desenvolvendo , aperfeiçoando e integrando sistemas, sou apaixonado por desenvolver e ensinar, nem tanto por escrever!.