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.
Otimizar seu código reduz o tempo e os custos de computação. Este estudo de caso demonstra como usar ferramentas de criação de perfil do Visual Studio para identificar e corrigir problemas de desempenho em um aplicativo .NET de exemplo. Se você quiser comparar as ferramentas de criação de perfil, consulte Qual ferramenta devo escolher?
Este guia aborda:
- Como usar as ferramentas de criação de perfil do Visual Studio para analisar e melhorar o desempenho.
- Estratégias práticas para otimizar o uso da CPU, a alocação de memória e as interações de banco de dados.
Aplique essas técnicas para tornar seus próprios aplicativos mais eficientes.
Estudo de caso de otimização
O aplicativo .NET de exemplo executa consultas em um banco de dados SQLite de blogs e postagens usando o Entity Framework. Ele executa muitas consultas, simulando um cenário de recuperação de dados do mundo real. O aplicativo se baseia no exemplo de introdução do Entity Framework, mas usa um conjunto de dados maior.
Os principais problemas de desempenho incluem:
- Alto uso da CPU: cálculos ineficientes ou tarefas de processamento aumentam o consumo e os custos da CPU.
- Alocação de memória ineficiente: o gerenciamento de memória ruim leva à coleta de lixo excessiva e à redução do desempenho.
- Sobrecargas de banco de dados: consultas ineficientes e chamadas excessivas de banco de dados prejudicam o desempenho.
Este estudo de caso usa ferramentas de criação de perfil do Visual Studio para identificar e resolver esses problemas, com o objetivo de tornar o aplicativo mais eficiente e econômico.
Desafio
Corrigir esses problemas de desempenho envolve vários desafios:
- Diagnosticar gargalos: identificar as causas raiz de altas sobrecargas de CPU, memória ou banco de dados requer o uso efetivo de ferramentas de criação de perfil e uma interpretação correta dos resultados.
- Restrições de conhecimento e recursos: a criação de perfil e a otimização exigem habilidades e experiência específicas, que podem nem sempre estar disponíveis.
Uma abordagem estratégica que combina ferramentas de criação de perfil, conhecimento técnico e testes cuidadosos é essencial para superar esses desafios.
Estratégia
Aqui está uma visão de alto nível da abordagem neste estudo de caso:
- Comece com um rastreamento de uso da CPU usando a ferramenta uso da CPU do Visual Studio. A ferramenta uso da CPU do Visual Studio é um bom ponto de partida para investigações de desempenho.
- Colete rastreamentos adicionais para análise de memória e banco de dados:
- Use a ferramenta de Alocação de Objetos do .NET para insights de memória.
- Use a ferramenta de Banco de Dados para examinar consultas e tempos de execução do SQL.
A coleta de dados requer as seguintes tarefas:
- Defina o aplicativo como versão de compilação.
- Selecione a ferramenta Uso da CPU no Criador de Perfil de Desempenho (Alt+F2).
- No Analisador de Desempenho, inicie o aplicativo e colete um traço.
Inspecionar áreas de alto uso da CPU
Depois de coletar um rastreamento com a ferramenta Uso da CPU e carregá-lo no Visual Studio, primeiro verificamos a página de relatório inicial .diagsession que mostra os dados resumidos. Use o link Detalhes abertos no relatório.
Na exibição de detalhes do relatório, abra a exibição Árvore de Chamadas. O caminho do código com maior uso de CPU no aplicativo é chamado de caminho frequente. O ícone de chama de caminho frequente (
) pode ajudar a identificar rapidamente problemas de desempenho que podem ser melhorados.
No modo de exibição Árvore de Chamadas, você pode ver o alto uso da CPU para o método GetBlogTitleX no aplicativo, usando cerca de 60% de participação no uso da CPU do aplicativo. No entanto, o valor de CPU própria para GetBlogTitleX é baixo, apenas cerca de 0,10%. Ao contrário do valor de CPU total, o valor de CPU Própria exclui o tempo gasto em outras funções, portanto, devemos procurar pelo o gargalo real mais para baixo na árvore de chamadas.
GetBlogTitleX faz chamadas externas para duas DLLs LINQ, que estão usando a maior parte do tempo de CPU, conforme evidenciado pelos valores muito altos de CPU própria. Essa é a primeira pista de que uma consulta LINQ pode ser uma área a ser otimizada.
Para obter uma árvore de chamadas visualizada e uma exibição diferente dos dados, abra a exibição Flame Graph. (Ou clique com o botão direito do mouse em GetBlogTitleX e escolha Visualizar no Gráfico de Chamas.) Aqui novamente, parece que o método GetBlogTitleX é responsável por grande parte do uso da CPU do aplicativo (mostrado em amarelo). As chamadas externas para as DLLs do LINQ aparecem abaixo da caixa GetBlogTitleX e estão usando todo o tempo de CPU para o método.
Coletar dados adicionais
Muitas vezes, outras ferramentas podem fornecer informações adicionais para ajudar a análise e isolar o problema. Neste estudo de caso, adotaremos a seguinte abordagem:
- Primeiro, examine o uso da memória. Pode haver uma correlação entre o alto uso da CPU e o alto uso de memória, portanto, pode ser útil examinar ambos para isolar o problema.
- Como identificamos as DLLs LINQ, também examinaremos a ferramenta de Banco de Dados.
Verificar o uso da memória
Para ver o que está acontecendo com o aplicativo em termos de uso de memória, coletamos um rastreamento usando a ferramenta Alocação de Objetos .NET (no C++, você pode usar a ferramenta Uso de Memória). O modo de exibição Árvore de Chamadas no rastreamento de memória mostra o caminho crítico e nos ajuda a identificar uma área de alto uso de memória. Não é surpresa, neste momento, o método GetBlogTitleX parece estar gerando muitos objetos! Mais de 900.000 alocações de objeto, na verdade.
A maioria dos objetos criados são cadeias de caracteres, matrizes de objetos e Int32s. Podemos ver como esses tipos são gerados examinando o código-fonte.
Verificar a consulta na ferramenta Banco de Dados
No Criador de Perfil de Desempenho, selecionamos a ferramenta Banco de Dados em vez de Uso da CPU (ou, selecione ambas). Depois de coletar um rastreamento, abra a guia Consultas na página de diagnóstico. Na guia Consultas para o rastreamento de banco de dados, você pode ver que a primeira linha mostra a consulta mais longa, 2446 ms. A coluna Registros mostra quantos registros a consulta lê. Você pode usar essas informações para comparação posterior.
Examinando a instrução SELECT gerada pelo LINQ na coluna Consulta, identificamos a primeira linha como a consulta associada ao método GetBlogTitleX. Para exibir a cadeia de caracteres de consulta completa, expanda a largura da coluna. A cadeia de caracteres de consulta completa é:
SELECT "b"."Url", "b"."BlogId", "p"."PostId", "p"."Author", "p"."BlogId", "p"."Content", "p"."Date", "p"."MetaData", "p"."Title"
FROM "Blogs" AS "b" LEFT JOIN "Posts" AS "p" ON "b"."BlogId" = "p"."BlogId" ORDER BY "b"."BlogId"
Observe que o aplicativo está recuperando muitos valores de coluna aqui, talvez mais do que precisamos. Vamos examinar o código-fonte.
Otimizar código
É hora de dar uma olhada no código-fonte GetBlogTitleX. Na ferramenta Banco de Dados, clique com o botão direito do mouse na consulta e escolha Ir para o Arquivo de Origem. No código-fonte para GetBlogTitleX, encontramos o código a seguir que usa LINQ para ler o banco de dados.
foreach (var blog in db.Blogs.Select(b => new { b.Url, b.Posts }).ToList())
{
foreach (var post in blog.Posts)
{
if (post.Author == "Fred Smith")
{
Console.WriteLine($"Post: {post.Title}");
}
}
}
Esse código usa foreach loops para pesquisar no banco de dados qualquer blog com "Fred Smith" como autor. Olhando para ele, você pode ver que muitos objetos estão sendo gerados na memória: uma nova matriz de objetos para cada blog no banco de dados, cadeias de caracteres associadas para cada URL e valores para propriedades contidas nas postagens, como ID do blog.
Fazemos uma pequena pesquisa e encontramos algumas recomendações comuns sobre como otimizar consultas LINQ. Como alternativa, podemos economizar tempo e deixar Copilot fazer a pesquisa por nós.
Se estivermos usando o Copilot, selecionamos Perguntar ao Copilot no menu de contexto e digitar a seguinte pergunta:
Can you make the LINQ query in this method faster?
Dica
Você pode usar comandos de barra, como /optimize, para ajudar a formular boas perguntas para o Copilot.
Neste exemplo, Copilot fornece as seguintes alterações de código sugeridas, juntamente com uma explicação.
public void GetBlogTitleX()
{
var posts = db.Posts
.Where(post => post.Author == "Fred Smith")
.Select(post => post.Title)
.ToList();
foreach (var postTitle in posts)
{
Console.WriteLine($"Post: {postTitle}");
}
}
Esse código inclui várias alterações para ajudar a otimizar a consulta:
- A cláusula
Wherefoi adicionada e um dos loopsforeachfoi eliminado. - Projetamos apenas a propriedade Title na instrução
Select, que é tudo que precisamos neste exemplo.
Em seguida, refazemos o teste usando as ferramentas de diagnóstico.
Resultados
Depois de atualizar o código, executamos novamente a ferramenta Uso da CPU para coletar um rastreamento. O modo de exibição de Árvore de Chamadas mostra que GetBlogTitleX está executando apenas 1754 ms, usando 37% do total de CPU do aplicativo, um aprimoramento significativo de 59%.
Alterne para a exibição do Flame Graph para conferir outra visualização da melhoria. Nesse modo de exibição, GetBlogTitleX também usa uma parte menor da CPU.
Verifique os resultados no rastreamento da ferramenta Banco de Dados e apenas dois registros são lidos usando essa consulta, em vez de 100.000! Além disso, a consulta é muito simplificada e elimina o LEFT JOIN desnecessário que foi gerado anteriormente.
Em seguida, verificamos novamente os resultados na ferramenta de Alocação de Objetos do .NET, e vemos que GetBlogTitleX é responsável apenas por 56.000 alocações de objetos, uma redução de quase 95% de 900.000!
ITERAR
Várias otimizações podem ser necessárias e podemos continuar a iterar com alterações de código para ver quais alterações melhoram o desempenho e ajudam a reduzir o custo de computação.
Próximas etapas
Os artigos e postagens de blog a seguir fornecem mais informações para ajudá-lo a aprender a usar as ferramentas de desempenho do Visual Studio com eficiência.
- Estudo de caso: isolar um problema de desempenho
- estudo de caso : desempenho duplo em menos de 30 minutos
- melhorando o desempenho do Visual Studio com a nova ferramenta de instrumentação