Partilhar via


Exibir dados do Application Insights Profiler para .NET

Digamos que você esteja executando um teste de desempenho da Web. Você precisará de rastreamentos para entender como seu aplicativo Web está sendo executado sob carga. Neste artigo, você:

  • Gere tráfego para seu aplicativo Web iniciando um teste de desempenho da Web ou iniciando uma sessão do Profiler sob demanda.
  • Visualize 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.

Gerar tráfego para o seu serviço do Azure

Para que o .NET Profiler carregue rastreamentos, seu serviço deve estar lidando ativamente com solicitações.

Se você habilitou recentemente o Profiler para .NET, execute um teste de carga curto com o Teste de Carga do Azure.

Se o seu serviço do Azure já tiver tráfego de entrada ou se você quiser apenas gerar tráfego manualmente, 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 para seu serviço do Azure, selecione Desempenho no menu à esquerda.

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

    Captura de ecrã do botão Profiler a partir do painel Desempenho.

  3. Quando a página de configurações do Profiler for carregada, selecione Perfil agora.

    Captura de ecrã das funcionalidades e definições da página do Profiler.

Ver rastreios

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

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

    Captura de ecrã da página do explorador de rastreio.

O explorador de rastreio apresenta as seguintes informações:

Filtro Description
Árvore de perfil v. Gráfico de chama Visualize os rastreamentos como uma árvore ou em forma de gráfico.
Caminho quente Selecione para abrir o maior nó folha. Na maioria dos casos, esse nó está perto de um gargalo de desempenho.
Dependências da estrutura Selecione esta opção para exibir cada uma das dependências da estrutura rastreada associadas aos rastreamentos.
Ocultar eventos Digite cadeias de caracteres para ocultar da exibição de rastreamento. Selecione Eventos sugeridos para sugestões.
Evento Nome do evento ou função. A árvore exibe uma combinação de código e eventos que ocorreram, como eventos SQL e HTTP. O evento principal representa a duração geral da solicitação.
Módulo O módulo onde ocorreu o evento ou função rastreada.
Tempo de thread O intervalo de tempo entre o início e o fim da operação.
Linha Cronológica O tempo em que a função ou evento estava sendo executado em relação a outras funções.

Como ler dados de desempenho

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

  • Amostras do ponteiro de instruções de cada CPU da máquina a cada milissegundo.
    • Cada amostra captura a pilha de chamadas completa do thread, fornecendo informações detalhadas em níveis altos e baixos de abstração.
  • Coleta eventos para rastrear a correlação e causalidade da atividade, incluindo:
    • Eventos de comutação de contexto
    • Eventos TPL (Biblioteca Paralela de Tarefas)
    • Eventos do pool de threads

A pilha de chamadas exibida na visualização da linha do tempo é o resultado da amostragem e da instrumentação. Como cada exemplo captura a pilha de chamadas completa do thread, ele inclui código do Microsoft .NET Framework e quaisquer outras estruturas referenciadas.

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.

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

Código de carregamento (clr! ThePreStub)

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

Se clr! ThePreStub leva tempo extra para uma solicitação, é a primeira solicitação para executar esse método. O tempo de execução do .NET Framework leva uma quantidade significativa de tempo para carregar o primeiro método. Considere:

  • Usando um processo de aquecimento que executa essa parte do código antes que os usuários o acessem.
  • Executando o Native Image Generator (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 o thread atual está aguardando a liberação de um bloqueio. Este texto é frequentemente apresentado quando:

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

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

Código de carregamento ([COLD])

Se o tempo de execução 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 uma vez durante o processo, no máximo.

Se o carregamento do código levar uma quantidade substancial 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 os usuários o acessem.

Enviar solicitação HTTP

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

Operação do banco de dados

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

À espera (AWAIT_TIME)

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

  • 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 está "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 parece estar no código da estrutura em vez do seu código, o .NET Profiler pode estar mostrando:

  • O código de 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 do Framework na parte superior da página para mostrar apenas seu código e facilitar a visualização da origem do AWAIT .

Tempo bloqueado

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

  • Um objeto de sincronização
  • Um tópico a ser disponibilizado
  • Um pedido para terminar

Assíncrono não gerenciado

Para que as chamadas assíncronas sejam 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 eventos e IDs de atividade, o .NET Profiler não pode rastrear o thread e as funções em execução no thread. Este item é rotulado como Assíncrono Não Gerenciado 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 coluna

A coluna When é 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 intervalos de tempo, onde as amostras inclusivas do nó se acumulam. Cada balde é representado como uma barra. A altura da barra representa um valor dimensionado. Para os 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 superior a 100% consumindo vários recursos. Por exemplo, se você usar duas CPUs durante um intervalo em média, obterá 200%.

Próximos passos

Saiba como ...