Compartilhar via


Exibir os dados do Application Insights Profiler para .NET

Digamos que você esteja executando um teste de desempenho Web. Você precisará de rastreamentos para entender o desempenho do aplicativo Web sob carga. Para que o .NET Profiler carregue rastreamentos, seu serviço deve estar tratando ativamente as solicitações. Neste artigo, você:

  • Gere tráfego para seu aplicativo Web iniciando um teste de desempenho da Web ou iniciando uma sessão sob demanda do Profiler.
  • Exiba os rastreamentos do Profiler após o teste de carga ou a sessão do Profiler.
  • Saiba como ler os dados de desempenho do Profiler e a pilha de chamadas.

Gere tráfego para seu serviço do Azure

Se você ativou recentemente o Profiler para .NET, deve executar um breve teste de carga com o Teste de Carga do Azure.

Se seu serviço do Azure já tiver tráfego de entrada ou se você apenas quiser gerar manualmente o tráfego, ignore o teste de carga e inicie uma sessão sob demanda do Profiler:

  1. Na página de visão geral do Application Insights, do serviço do Azure selecione Desempenho no menu à esquerda.

  2. No painel Desempenho, selecione Profiler no menu superior para obter as configurações do Profiler.

    Captura de tela do botão Profiler da folha de Desempenho.

  3. Depois que a página de configurações do Profiler for carregada, selecione Criar Perfil Agora.

    Captura de tela dos recursos e configurações da página do Profiler.

Exibir rastreamentos

  1. Depois que as sessões do Profiler terminarem de ser executadas, retorne ao painel Desempenho.

  2. Em Explorar..., selecione Rastreamentos do Profiler para exibir os rastreamentos.

    Captura de tela da página do explorador de rastreamento.

O explorador de rastreamento exibe as seguintes informações:

Filtrar Descrição
Árvore de perfil v. Grafo de chama Exiba os traços como uma árvore ou em forma de gráfico.
Caminho crítico Selecione para abrir o nó folha maior. Na maioria dos casos, este nó está próximo a um gargalo de desempenho.
Dependências do framework Selecione para exibir cada uma das dependências da estrutura rastreada associadas aos rastreamentos.
Ocultar eventos Digite as cadeias de caracteres a serem ocultadas na exibição de rastreamento. Selecione Eventos sugeridos para obter sugestões.
Evento Nome do evento ou função. A árvore exibe uma combinação de código e eventos que ocorreram, tais como eventos SQL e HTTP. Os principais eventos representa a duração total da solicitação.
Módulo O módulo em que o evento ou função rastreada ocorreu.
Tempo de execução do thread Intervalo de tempo entre o início e o final da operação.
Linha do tempo Horário em que a função ou evento estava sendo executado com relação a outras funções.

Ler dados de desempenho

O Profiler para .NET usa uma combinação de métodos de amostragem e instrumentação para analisar o desempenho do aplicativo. Ao realizar uma coleta detalhada, o Profiler .NET:

  • Amostra o ponteiro de instrução de cada CPU do computador a cada milissegundo.
    • Cada exemplo captura a pilha de chamadas completa do thread, fornecendo informações detalhadas nos níveis alto e baixo de abstração.
  • Coleta eventos para acompanhar a correlação de atividades e causalidade, incluindo:
    • Eventos de alternância de contexto
    • Eventos da TPL (Task Parallel Library)
    • Eventos de pool de threads

A pilha de chamadas exibida na exibição de linha do tempo é o resultado da amostragem e instrumentação. Como cada amostra captura a pilha de chamadas completa do thread, ela inclui o código do Microsoft .NET Framework e quaisquer outras estruturas que você referenciar.

Alocação de objeto (clr!JIT_New ou clr!JIT_Newarr1)

clr!JIT_New e clr!JIT_Newarr1 são funções auxiliares no .NET Framework que alocam memória de um heap gerenciado.

  • clr!JIT_New é invocado quando um objeto é alocado.
  • clr!JIT_Newarr1 é invocado quando uma matriz de objetos é alocada.

Essas duas funções geralmente funcionam rapidamente. Se o clr!JIT_New ou o clr!JIT_Newarr1 ocupar um tempo em sua linha do tempo, o código talvez esteja alocando muitos objetos e consumindo quantidades significativas de memória.

Carregando código (clr!ThePreStub)

clr!ThePreStub é uma função auxiliar no .NET Framework que prepara o código para execução inicial, que geralmente inclui compilação JIT (just-in-time). Para cada método C#, clr!ThePreStub deve ser invocado no máximo uma vez durante um processo.

Se clr!ThePreStub demorar muito para uma solicitação, será a primeira solicitação a executar esse método. O runtime do .NET Framework leva um tempo significativo para carregar o primeiro método. Considere:

  • Use um processo de aquecimento que execute essa parte do código antes que seus usuários a acessem.
  • Executar o Gerador de Imagem Nativa (ngen.exe) em seus assemblies.

Contenção de bloqueio (clr!JITutil_MonContention ou clr!JITutil_MonEnterWorker)

clr!JITutil_MonContention ou clr!JITutil_MonEnterWorker indicam que a conversa atual está esperando a liberação de um bloqueio. Esse texto geralmente é exibido quando você:

  • Executa uma instrução LOCK em C#,
  • Invoca o método Monitor.Enter ou
  • Invoca um método com o atributo MethodImplOptions.Synchronized.

Normalmente, a contenção de bloqueio ocorre quando um thread A adquire um bloqueio e um thread B tenta adquirir o mesmo bloqueio antes que o thread A o libere.

Carregando código ([COLD])

Se o runtime do .NET Framework estiver executando código não otimizado pela primeira vez, o nome do método conterá [COLD]:

mscorlib.ni![COLD]System.Reflection.CustomAttribute.IsDefined

Para cada método, ele deve ser exibido no máximo uma vez durante o processo.

Se o carregamento de um código leva uma quantidade significativa de tempo para uma solicitação, é a solicitação que inicia a execução da parte não otimizada do método. Considere usar um processo de aquecimento que execute essa parte do código antes que seus usuários a acessem.

Enviar solicitação de HTTP

Métodos como HttpClient.Send indicam que o código está aguardando a conclusão de uma solicitação HTTP.

Operação de banco de dados

Método como SqlCommand.Execute indicam que o código está aguardando a conclusão de uma operação de banco de dados.

Aguardando (AWAIT_TIME)

AWAIT_TIME indica que o código está aguardando a conclusão de outra tarefa. Esse atraso ocorre com a instrução AWAIT em C#. Quando o código faz um AWAIT em C#:

  • A conversa é encerrada e o controle é retornado ao pool de threads.
  • Não há conversa bloqueada aguardando o AWAIT terminar.

No entanto, logicamente o thread que fez o AWAIT é "bloqueado" aguardando a conclusão da operação. A instrução AWAIT_TIME indica o tempo bloqueado aguardando a conclusão da tarefa.

Se AWAIT_TIME parecer estar no código do framework em vez de no seu código, o Profiler para .NET pode estar mostrando:

  • O código da estrutura usado para executar o AWAIT
  • Código usado para gravar telemetria sobre o AWAIT

Você pode desmarcar a caixa de seleção Dependências da estrutura na parte superior da página para mostrar apenas seu código e facilitar a visualização de onde o AWAIT se origina.

Tempo de bloqueio

BLOCKED_TIME indica que o código está aguardando até que outro recurso esteja disponível. Por exemplo, pode estar aguardando:

  • Um objeto de sincronização
  • Uma conversa disponível
  • A conclusão de uma solicitação

Assíncrono Não Gerenciado

Para que chamadas assíncronas possam ser rastreadas entre threads, o .NET Framework emite eventos ETW e passa IDs de atividade entre threads. Como o código não gerenciado (nativo) e alguns estilos mais antigos de código assíncrono não têm esses IDs de atividade e eventos, o Profiler para .NET não pode rastrear o thread e as funções em execução nele. Esse item é rotulado como Unmanaged Async na pilha de chamadas. Baixe o arquivo ETW para usar o PerfView para obter mais informações.

Tempo de CPU

A CPU está ocupada executando as instruções.

Tempo de disco

O aplicativo está executando operações de disco.

Tempo de rede

O aplicativo está executando operações de rede.

Quando

A coluna Quando é uma visualização da variedade de amostras inclusivas coletadas para um nó ao longo do tempo. O intervalo total da solicitação é dividido em 32 buckets de tempo, onde as amostras inclusivas do nó se acumulam. Cada bucket é representado como uma barra. A altura da barra representa um valor escalonado. Nos seguintes nós, a barra representa o consumo de um dos recursos durante o bucket:

  • Nodos marcados como CPU_TIME ou BLOCKED_TIME.
  • Nós com um relacionamento óbvio com o consumo de um recurso (por exemplo, CPU, disco ou conversa).

Para essas métricas você pode obter um valor maior que 100%, consumindo vários recursos. Por exemplo, se você usar, em média, duas CPUs durante um intervalo, obterá 200%.

Próximas etapas

Saiba como...