Debug Profundo
Descobrindo a causa Raiz dos problemas com Dumps de memória
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.
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
- Windbg é um software que analisa a memória, podemos usar o WindbgPreview da loja Ms.
- o Windbg pode analisar um arquivo com o conteúdo da memória, um Dump, ou um .exe vivo.
- 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.
- Os cenários mais comuns são Alta Demanda de processamento, Memory Leak ou situações para encontrar erros e Exceptions.
- 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
- no .net os símbolos são armazenados no *.pdb.
- Além dos símbolos do seu código existem símbolos da infraestrutura, e dos frameworks .net core e sistema operacional.
- Existem problemas de Compatibilidade entre as plataformas da aplicação 32 bits e 64 bits, Dumps devem seguir a Arquitetura do sistema.
- 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
- O básico para fazer uma análise descente do DUMP é conhecer a plataforma
- Podemos publicar um PDB junto da aplicação, pois não temos impacto na performance nem mesmo em segurança, isso é um mito comum
- Falando de DEVOPS pulicar o PDB em um Simbols Server é uma boa prática pois podemos diminuir o tempo de deploy
- 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
- Abra o DebugDiag Collection
- Selecione o Botão Add Rule
- Escolha o Tipo da Regra por exemplo Crash (pegar Exception)
- Na próxima telinha escolha como você vai filtrar os processos, por exemplo A Specific NT Service
- Caso tenha escolhido a opção acima escolha o serviço
- Agora Clicamos em Advanced Settings Botão Exceptions
- Adicionamos uma exception
- No caos de uma aplicação .net vamos escolher CLR Exception
- No Dropdown ActionType Escolha Full User dump
- Action Limit deixa 1
- Na tela anterior na caixa de Unconfigured First Change Exception escolha Full User Dump no action Type e 1 para o Action Limit
- 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
- peb: Mais informações sobre o processo (threads, stacks, locals, Enviroments Variables)
- runaway: Quem está rodadndo, vai mostrar as threads e podemos navegar entre as threads usando ~<numero da therad> s
- dv: Mostrar valores das variáveis.
- cordll -T coreclr.dll -N -ve Tem que fazer mesmo com Erro
- verifyheap: verificar se sua memória está ok
- ~<numero da therad> s: Trocar de thread
- clrstack: stack do .net
- IP2MD [hexadecimal da memória]: mostra as definições de meta dados, ou seja, o nome do método
- dumpil [hexadecimal da memória]
- dumpstack -EE: Verificar a stack
- clrstack -a: Verificar a stack e mostra os valores das variáveis em hexadecimal
- EEVersion: traz dados do GC e do framework
- EEHeap — gc: o que tem na heap nesse momento
- Dumpheap -stat: ele vai olhar para todos os objetos da memória e vai mostrar o tamanho deles em ordem.
- gcroot [hexadecimal]: quem é o dono desse objeto, quem está impedindo esse cara de ser coletado.
- lastevent: normalmente não funciona para o .net, mas é ima tentativa em situações de crash
- dso: lista conjunto de elementos do stack
Analise Memory Leak .net core Windbg
- Carregar o SSO
- Verificar a heap (verifyheap)
- Verificar a memória gerenciadas
- Verificar o tamanho dos objetos me memória (Dumpheap -stat)
- Filtrar a lista de objetos dessa lista acima
- Analisar o conteúdo dos objetos
DebugDiag Analysis
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.
Referencias
- https://docs.microsoft.com/pt-br/dotnet/framework/tools/sos-dll-sos-debugging-extension
- https://www.microsoft.com/en-us/download/details.aspx?id=53304
- https://learn.microsoft.com/en-us/sysinternals/downloads/procdump
- Talk Coders — Analisando Dumps de Memória de Aplicações .NET
- Analisando dumps de memória de aplicações .NET
- Performance máxima em .NET: como entender o GC pode acelerar apps em 10x
- C# AVANÇADO — Gerenciamento de memória
- Utilizando IntelliTrace para debugar suas aplicações | Using Intellitrace for application debug
- Gerenciamento de Memória (Parte 1) | Entendendo Back-end para Iniciantes (Parte 5)
- Hunting .NET memory leaks with Windbg
- Buscando performance em .NET? Te ajudo a dar os primeiros passos para entender IL, JIT, WinDBG e Assembly
- Coletando e analisando dump com o .NET