Depurar alto uso da CPU no .NET Core
Este artigo aplica-se a: ✔️ SDK do .NET Core 3.1 e versões posteriores
Neste tutorial, você aprenderá a depurar um cenário de uso excessivo da 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 deixará de responder e experimentará acúmulo de threads. Você aprenderá como usar várias ferramentas para diagnosticar esse cenário com vários dados de diagnóstico.
Neste tutorial, vai:
- Investigue o alto uso da CPU
- Determinar o uso da CPU com contadores de pontos
- Usar dotnet-trace para geração de rastreamento
- Desempenho do perfil no PerfView
- Diagnosticar e resolver o uso excessivo da 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.
- contadores dotnet para monitorar o uso da CPU.
Contadores de CPU
Antes de tentar coletar dados de diagnóstico, você precisa observar uma condição alta da CPU. Execute o aplicativo de exemplo usando o seguinte comando do diretório raiz do projeto.
dotnet run
Para localizar a ID do processo, use o seguinte comando:
dotnet-trace ps
Anote o ID do processo na saída do comando. Nosso ID de processo era 22884
, mas o seu será diferente. Para verificar o uso atual da CPU, use o comando dotnet-counters tool:
dotnet-counters monitor --refresh-interval 1 -p 22884
O refresh-interval
é o número de segundos entre os valores da CPU de sondagem do contador. O resultado deve ser semelhante ao seguinte:
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 0
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
Com o aplicativo Web em execução, imediatamente após a inicialização, a CPU não está sendo consumida e é relatada em 0%
. Navegue até a api/diagscenario/highcpu
rota com 60000
o parâmetro route:
https://localhost:5001/api/diagscenario/highcpu/60000
Agora, execute novamente o comando dotnet-counters . Se estiver interessado em monitorar apenas o cpu-usage
contador, adicione '--counters System.Runtime[cpu-usage]' ao comando anterior. Não temos certeza se a CPU está sendo consumida, então vamos monitorar a mesma lista de contadores como acima para verificar se os valores dos contadores estão dentro do intervalo esperado para a nossa aplicação.
dotnet-counters monitor -p 22884 --refresh-interval 1
Você deve ver um aumento no uso da CPU como mostrado abaixo (dependendo da máquina host, espere variar o uso da CPU):
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 25
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
Durante toda a duração da solicitação, o uso da CPU irá pairar em torno da porcentagem aumentada.
Gorjeta
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á funcionando mais alto do que o esperado. Identificar os efeitos de um problema é fundamental para encontrar a causa. Vamos usar o efeito do alto consumo de CPU, além de ferramentas de diagnóstico para encontrar a causa do problema.
Analise a alta CPU com o Profiler
Ao analisar um aplicativo com alto uso de CPU, você precisa de uma ferramenta de diagnóstico que possa fornecer informações sobre o que o código está fazendo. A escolha habitual é um profiler, e há diferentes opções de profiler para escolher. dotnet-trace
pode ser usado em todos os sistemas operacionais, no entanto, suas limitações de viés de ponto seguro e pilhas de chamadas somente gerenciadas resultam em informações mais gerais em comparação com um profiler com reconhecimento de kernel como 'perf' para Linux ou ETW para Windows. Se sua investigação de desempenho envolver apenas código gerenciado, geralmente dotnet-trace
será suficiente.
A perf
ferramenta pode ser usada para gerar perfis de aplicativo .NET Core. Vamos demonstrar esta ferramenta, embora 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. Este map
arquivo é usado por para mapear endereços de CPU para funções geradas por JIT por perf
nome. Para obter mais informações, consulte Exportar mapas de perf e jit dumps.
Nota
O .NET 6 padroniza o prefixo DOTNET_
em vez de variáveis de ambiente que configuram o comportamento em tempo de execução do COMPlus_
.NET. No entanto, o prefixo COMPlus_
continuará a funcionar. Se você estiver usando uma versão anterior do tempo de execução do .NET, ainda deverá usar o prefixo COMPlus_
para variáveis de ambiente.
Execute o destino de depuração de exemplo na mesma sessão de terminal.
export DOTNET_PerfMapEnabled=1
dotnet run
Exerça novamente o ponto de extremidade da API de alta CPU (https://localhost:5001/api/diagscenario/highcpu/60000
). Enquanto ele estiver sendo executado dentro da solicitação de 1 minuto, execute o comando com sua ID de perf
processo:
sudo perf record -p 2266 -g
O perf
comando inicia o processo de coleta de desempenho. Deixe-o funcionar por cerca de 20 a 30 segundos e pressione Ctrl+C para sair do processo de coleta. Você pode usar o mesmo perf
comando para ver a saída do rastreamento.
sudo perf report -f
Você também pode gerar um gráfico 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
Este comando gera um flamegraph.svg
que você pode visualizar no navegador para investigar o problema de desempenho:
Analisando dados de alta CPU com o Visual Studio
Todos os arquivos *.nettrace podem ser analisados no Visual Studio. Para analisar um arquivo Linux *.nettrace no Visual Studio, transfira o arquivo *.nettrace, além dos outros documentos necessários, para uma máquina Windows e, em seguida, 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
- contadores dotnet para verificar o uso de memória gerenciada
- dotnet-dump para coletar e analisar um arquivo de despejo
- dotnet/diagnóstico