Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo se aplica a: ✔️ SDK do .NET Core 3.1 e versões posteriores
Neste tutorial, você aprenderá a depurar um cenário de uso excessivo de CPU. Usando o exemplo fornecido ASP.NET repositório de código-fonte do aplicativo Web Core , você pode causar um deadlock intencionalmente. O ponto de extremidade interromperá a resposta e experimentará o acúmulo de threads. Você aprenderá a usar várias ferramentas para diagnosticar esse cenário com várias partes principais dos dados de diagnóstico.
Neste tutorial, você vai:
- Investigar o alto uso da CPU
- Determinar o uso da CPU com contadores dotnet
- Usar o dotnet-trace para a geração de rastreamento
- Desempenho do perfil no PerfView
- Diagnosticar e resolver uso excessivo de CPU
Pré-requisitos
O tutorial usa:
- SDK do .NET Core 3.1 ou uma versão posterior.
- Exemplo de destino de depuração para disparar o cenário.
- dotnet-trace para listar processos e gerar um perfil.
- dotnet-counters para monitorar o uso da cpu.
Contadores de CPU
Antes de tentar este tutorial, instale a versão mais recente dos contadores dotnet:
dotnet tool install --global dotnet-counters
Se o aplicativo estiver executando uma versão do .NET mais antiga que o .NET 9, a interface do usuário de saída de contadores dotnet terá uma aparência ligeiramente diferente; consulte dotnet-counters para obter detalhes.
Antes de tentar coletar dados de diagnóstico, você precisa observar uma condição de CPU alta. Execute o aplicativo de exemplo usando o comando a seguir do diretório raiz do projeto.
dotnet run
Para verificar o uso atual da CPU, use o comando da ferramenta dotnet-counters :
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
A saída deve ser semelhante à seguinte:
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.109 0
user 0.453 0
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
Concentrando-se nos Last Delta valores de dotnet.process.cpu.time, estes nos dizem quantos segundos dentro do período de atualização (atualmente definido como o padrão de 1 s) a CPU tem sido ativa. Com o aplicativo Web em execução, imediatamente após a inicialização, a CPU não está sendo consumida e esses deltas são ambos 0. Navegue até a api/diagscenario/highcpu rota com 60000 o parâmetro de rota:
https://localhost:5001/api/diagscenario/highcpu/60000
Agora, execute novamente o comando dotnet-counters .
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Você deverá ver um aumento no uso da CPU, conforme mostrado abaixo (dependendo do computador host, espere um uso variável da CPU):
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.344 0.013
user 14.203 0.963
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
Durante toda a solicitação, o uso da CPU focalizará o valor aumentado.
Dica
Para visualizar um uso ainda maior da CPU, você pode exercer esse ponto de extremidade em várias guias do navegador simultaneamente.
Neste ponto, você pode dizer com segurança que a CPU está em execução maior do que você espera. Identificar os efeitos de um problema é fundamental para encontrar a causa. Usaremos o efeito do alto consumo de CPU além das ferramentas de diagnóstico para encontrar a causa do problema.
Analisar alta CPU com o Criador de Perfil
Ao analisar um aplicativo com alto uso de CPU, você precisa de uma ferramenta de diagnóstico que possa fornecer insights sobre o que o código está fazendo. A opção usual é um criador de perfil e há diferentes opções de criador de perfil para escolher.
dotnet-trace pode ser usado em todos os sistemas operacionais, no entanto, suas limitações de desvio de ponto seguro e de chamadas somente gerenciadas resultam em informações mais gerais em comparação com um criador de perfil com reconhecimento de kernel, como 'perf' para Linux ou ETW para Windows. Se a investigação de desempenho envolver apenas o código gerenciado, geralmente dotnet-trace será suficiente.
A perf ferramenta pode ser usada para gerar perfis de aplicativo do .NET Core. Demonstraremos essa ferramenta, embora o dotnet-trace também possa ser usado. Saia da instância anterior do destino de depuração de exemplo.
Defina a DOTNET_PerfMapEnabled variável de ambiente para fazer com que o aplicativo .NET crie um map arquivo no /tmp diretório. Esse map arquivo é usado para perf mapear endereços de CPU para funções geradas por JIT por nome. Para obter mais informações, consulte Exportar mapas perf e despejos de jit.
Execute o destino de depuração de exemplo na mesma sessão de terminal.
export DOTNET_PerfMapEnabled=1
dotnet run
Exercite o ponto de extremidade da API de CPU alta (https://localhost:5001/api/diagscenario/highcpu/60000) novamente. Enquanto ele estiver em execução dentro da solicitação de 1 minuto, execute o comando com a perf ID do processo:
sudo perf record -p 2266 -g
O perf comando inicia o processo de coleta de desempenho. Deixe que ele seja executado por cerca de 20 a 30 segundos e pressione Ctrl+C para sair do processo de coleção. Você pode usar o mesmo perf comando para ver a saída do rastreamento.
sudo perf report -f
Você também pode gerar um grafo de chama usando os seguintes comandos:
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
Esse comando gera um flamegraph.svg que você pode exibir no navegador para investigar o problema de desempenho:
Analisando dados altos da CPU com o Visual Studio
Todos os arquivos *.nettrace podem ser analisados no Visual Studio. Para analisar um arquivo *.nettrace do Linux no Visual Studio, transfira o arquivo *.nettrace, além dos outros documentos necessários, para um computador Windows e abra o arquivo *.nettrace no Visual Studio. Para obter mais informações, consulte Analisar dados de uso da CPU.
Consulte também
- dotnet-trace para listar processos
- dotnet-counters para verificar o uso de memória gerenciada
- dotnet-dump para coletar e analisar um arquivo de despejo
- dotnet/diagnostics