Adicionar dados do Application Insights Profiler

Digamos que você esteja executando um teste de desempenho Web. Você precisará de rastreamentos para entender o desempenho do aplicativo Web sob carga. Neste artigo, você vai:

  • 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

Para que o Profiler carregue rastreamentos, seu serviço precisa estar manipulando ativamente as solicitações.

Se você tiver habilitado o Profiler recentemente, execute um teste de carga curto 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.

    Screenshot of the Profiler button from the Performance pane.

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

    Screenshot of Profiler page features and settings.

Exibir rastreamentos

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

  2. Em Analisar entrada..., selecione rastreamentos do Profiler para exibir os rastreamentos.

    Screenshot of trace explorer page.

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

Filtrar Descrição
Árvore do perfil v. Grafo de chama Exiba os rastreamentos como uma árvore ou em forma de grafo.
Afunilamento Selecione para abrir o nó folha maior. Na maioria dos casos, esse nó está próximo de 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 para ocultar o modo de 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 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.

Como ler dados de desempenho

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

  • 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 controlar a correlação e a causalidade da atividade, incluindo:
    • Eventos de alternância de contexto
    • Eventos da biblioteca de paralelismo de tarefas (TPL)
    • Eventos de pool de threads

A pilha de chamadas mostrada na exibição de linha do tempo é o resultado da amostragem e da 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 objetos (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.
  • Executando o Gerador de Imagens Nativas (ngen.exe) em seus assemblies.

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

clr!JITutil_MonContention ou clr!JITutil_MonEnterWorker indica que o thread atual está aguardando um bloqueio ser liberado. 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 execução inicial da solicitaçã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#:

  • O thread desenrola e retorna o controle para o pool de threads.
  • Não há nenhum thread bloqueado aguardando a conclusão do AWAIT.

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 o AWAIT_TIME parecer estar no código da estrutura em vez do seu código, o Criador de perfil poderá mostrar:

  • 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 bloqueado

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

  • Um objeto de sincronização
  • A disponibilização de um thread
  • A conclusão de uma solicitação

Unmanaged Async

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 não pode rastrear o thread e as funções em execução no thread. 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 colunas

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ó são acumuladas. Cada bucket é representado como uma barra. A altura da barra representa um valor em escala. Nos seguintes nós, a barra representa o consumo de um dos recursos durante o bucket:

  • Nós marcados como CPU_TIME ou BLOCKED_TIME.
  • Nós com uma relação óbvia com o consumo de um recurso (por exemplo, uma CPU, disco ou thread).

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...