Partilhar via


Isolar um problema de desempenho (C#, Visual Basic, F#)

Neste artigo, você aprenderá como usar ferramentas de criação de perfil para investigar problemas de desempenho e isolar áreas problemáticas.

Em vez de fornecer instruções passo a passo, a intenção aqui é mostrar como usar as ferramentas de criação de perfil com eficiência e como interpretar os dados. Assim como a ferramenta Uso da CPU, a ferramenta Contadores do .NET também é um bom ponto de partida para uma investigação de desempenho. Após identificar dados interessantes, você pode usar outras ferramentas de criação de perfil para fazer uma investigação mais profunda. Para comparar ferramentas, confira Which tool should I choose?

Sobre o aplicativo de exemplo

As capturas de tela neste artigo têm como base um aplicativo ASP.NET que executa consultas em um banco de dados simulado. O exemplo tem como base a Amostra de Diagnóstico.

Iniciar uma investigação

  • Inicie sua investigação observando as métricas do contador do .NET enquanto coleta dados de desempenho.
  • Em seguida, para obter informações adicionais a fim de ajudar a isolar problemas, considere coletar um rastreamento usando uma das outras ferramentas de criação de perfil, como a ferramenta Uso da CPU, a ferramenta Instrumentação e outras.

Para fazer coleta de dados, siga estas etapas (não apresentadas neste artigo):

  • Definir seu aplicativo como um build de Versão.
  • Selecione a ferramenta Contadores do .NET no Criador de Perfil de Desempenho (Alt+F2). (As etapas posteriores envolvem a ferramenta Instrumentação.)
  • No Criador de Perfil de Desempenho, inicie o aplicativo.

Verificar contadores de desempenho

Ao executar o aplicativo, exiba os contadores na ferramenta Contadores do .NET. Para investigações iniciais, algumas métricas-chave para ficar de olho incluem:

  • CPU Usage. Observe esse contador para ver se há algum problema de desempenho com uso baixo ou elevado da CPU. Isso pode ser uma pista quanto a tipos específicos de problemas de desempenho. Por exemplo:
    • Se houver uso elevado da CPU, use a ferramenta Uso da CPU para identificar áreas nas quais você possa otimizar o código. Para ver um tutorial sobre isso, consulte o Guia de otimização de código para iniciantes.
    • Se houver uso baixo da CPU, use a ferramenta Instrumentação para identificar contagens de chamadas e tempo médio de função com base no tempo do relógio de parede. Isso pode ajudar você a identificar problemas como contenção ou escassez de pool de threads.
  • Allocation Rate. Para um aplicativo Web que atenda a solicitações, a taxa deve ser razoavelmente estável.
  • GC Heap Size. Observe esse contador para ver se o uso de memória está aumentando continuamente e potencialmente vazando. Se parecer alto, você pode usar uma das ferramentas de uso de memória.
  • Threadpool Thread Count. Para um aplicativo Web que atenda a solicitações, observe esse contador para ver se a contagem de threads está se mantendo estável ou aumentando a uma taxa constante.

Aqui está um exemplo mostrando como CPU Usage está baixo, enquanto ThreadPool Thread Count está relativamente alto.

Captura de tela dos contadores exibidos na ferramenta Contadores do .NET.

Uma contagem de threads cada vez maior com um baixo uso da CPU pode ser um indicador de insuficiência do pool de threads. O pool de threads é forçado a continuar iniciando novos threads. A insuficiência do pool de threads ocorre quando o pool não tem threads disponíveis para processar novos itens de trabalho e costuma causar lentidão na resposta dos aplicativos.

Com base no baixo uso da CPU e na contagem relativamente alta de threads, e trabalhando com a hipótese de um possível caso de insuficiência do pool de threads, mude para a ferramenta Instrumentação.

Investigar contagens de chamadas e dados de tempo

Vamos dar uma olhada em um rastreamento da ferramenta Instrumentação para ver se conseguimos descobrir mais sobre o que está acontecendo com os threads.

Quando os dados de diagnóstico forem carregados, verifique primeiro a página inicial do relatório .diagsession que mostra os principais insights e o Hot Path. No rastreamento da Instrumentação, o Caminho crítico mostra o caminho do código com os maiores tempos de função em seu aplicativo. Essas seções podem fornecer dicas para ajudar você a identificar rapidamente problemas de desempenho que podem ser melhorados.

No rastreamento coletado, use o link Abrir detalhes no relatório e selecione Flame Graph.

Captura de tela do Flame Graph na ferramenta Instrumentação.

A visualização do Flame Graph mostra que a função QueryCustomerDB é responsável por uma parte significativa do tempo de execução do aplicativo.

Clique com o botão direito do mouse na função QueryCustomerDB e escolha Exibir na árvore de chamadas.

Captura de tela da Árvore de chamadas na ferramenta Instrumentação.

No modo de exibição Árvore de chamadas, você verá que o Caminho crítico (ícone de chama) inclui a função QueryCustomerDB, que indica um possível problema de desempenho.

Em relação ao tempo gasto em outras funções, os valores Próprio e Média próprio para a função QueryCustomerDB estão muito altos. Ao contrário de Total e Média total, os valores de Próprio excluem o tempo gasto em outras funções, portanto, esse é um bom lugar para procurar o gargalo de desempenho.

Dica

Se os valores de Próprio estivessem relativamente baixos em vez de altos, você provavelmente examinaria as consultas efetivas chamadas pela função QueryCustomerDB.

Clique duas vezes na função QueryCustomerDB para mostrar o código-fonte da função.

public ActionResult<string> QueryCustomerDB()
{

    Task dbTask = QueryCustomerFromDbAsync("Dana");
    return "success:tasksleepwait";
}

Com um pouco de pesquisa, descobrimos que esse código está chamando uma API assíncrona sem usar await. Esse é o padrão de código síncrono sobre assíncrono, que é uma causa comum de insuficiência do pool de threads e pode bloquear threads.

Para solucionar, use await.

public async Task<ActionResult<string>> TaskAsyncWait()
{
    Customer c = await PretendQueryCustomerFromDbAsync("Dana");
    return "success:taskasyncwait";
}

Se localizar problemas de desempenho relacionados a consultas de banco de dados, você poderá usar a ferramenta Banco de Dados para investigar se determinadas chamadas são mais lentas. Esses dados podem indicar uma oportunidade de otimizar consultas. Para obter um tutorial que mostra como usar a ferramenta Banco de dados para investigar um problema de desempenho, consulte o Guia de otimização de código para iniciantes. A ferramenta Banco de Dados é compatível com .NET Core com ADO.NET ou Entity Framework Core.

Para obter visualizações no Visual Studio para comportamento individual de thread, você pode usar a janela Pilhas paralelas durante a depuração. Essa janela mostra threads individuais juntamente com informações sobre threads que estão aguardando, as threads que elas estão aguardando e deadlocks.

Para obter mais informações sobre a insuficiência do pool de threads, consulte Detectando a insuficiência do pool de threads.

Próximas etapas

Os artigos e as postagens no blog apresentados a seguir fornecem mais informações para ajudar você a aprender a usar as ferramentas de desempenho do Visual Studio de maneira efetiva.