Depurar um despejo de memória gerenciado com analisadores de diagnóstico do .NET
Neste tutorial, você irá:
- Abrir um despejo de memória
- Selecionar e executar analisadores no despejo
- Examinar os resultados dos analisadores
- Navegar até o código problemático
No exemplo descrito neste artigo, a preocupação é que seu aplicativo não responde às solicitações em tempo hábil.
Abrir um despejo de memória no Visual Studio
Abra o despejo de memória no Visual Studio usando o comando de menu Arquivo > Abrir > Arquivo e selecione o despejo de memória.
Observe na página Resumo do Despejo de Memória uma nova Ação chamada Executar Análise de Diagnóstico.
Selecione esta ação para iniciar o depurador e abrir a nova página Análise de Diagnóstico com uma lista de opções de analisador disponíveis organizadas de acordo com o sintoma subjacente.
Selecionar e executar analisadores no despejo
Para investigar esses sintomas, as melhores opções estão disponíveis em Capacidade de Resposta ao Processo, pois correspondem melhor ao problema neste exemplo.
Clique no botão Analisar para iniciar o processo de investigação
O analisador apresentará resultados com base na combinação de informações de processo e dados CLR capturados no despejo de memória.
Examinar os resultados dos analisadores
Nesse caso, o analisador encontrou dois erros. Selecione o resultado do analisador para ver o Resumo da Análise e a Correção sugerida.
O Resumo da Análise afirmou que o “pool de threads CLR está sofrendo privação”. Essas informações sugerem que o CLR atualmente usou todos os threads do pool de threads disponíveis, o que significa que seu serviço não pode responder a novas solicitações até que um thread seja liberado.
Observação
A Correção nesse caso é "Não aguardar de forma síncrona Monitores, Eventos, Tarefa ou outros objetos que possam bloquear seu thread. Veja se você pode atualizar o método para ser assíncrono.".
Navegar até o código problemático
Meu próximo trabalho é encontrar esse código problemático.
Ao clicar no link Mostrar pilha de chamadas, o Visual Studio mudará imediatamente para os threads que exibem esse comportamento.
A janela Pilha de Chamadas mostrará métodos que podem distinguir rapidamente entre meu código (SyncOverAsyncExmple.) e o código do Framework (System.).
Cada registro de ativação de chamadas corresponde a um método e dois cliques nos registros de ativação farão o Visual Studio navegar até o código que levou diretamente a esse cenário no thread.
Neste exemplo, não há símbolos ou código; no entanto, na página Símbolos não carregados, você pode selecionar a opção Descompilar Código-fonte.
Na origem descompilada abaixo, é evidente que uma tarefa assíncrona (ConsumeThreadPoolThread) está chamando uma função de bloqueio síncrona.
Observação
O método "DoSomething()" que contém um método WaitHandle.WaitOne, que bloqueia o thread do pool de threads atual até receber um sinal.
Para melhorar a capacidade de resposta dos aplicativos, é importante remover o bloqueio de código síncrono de todos os contextos assíncronos.