Inspecionar rastros

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

A visualização de rastros no CPU Profiler oferece várias maneiras de visualizar informações de rastros gravados.

Para rastreamentos de métodos e funções, você pode ver a Call Chart diretamente na linha do tempo Threads e nas guias Flame Chart, Top Down, Bottom Up e Events do painel Analysis. No caso de frames da pilha de chamadas, é possível ver a parte do código que foi executada e por que ela foi invocada. Nos rastreamentos do sistema, é possível ver os Trace Events diretamente na linha do tempo Threads, além das guias Flame Chart, Top Down, Bottom Up e Events no painel Analysis.

Atalhos de mouse e teclado estão disponíveis para facilitar a navegação por Call Charts ou Trace Events.

Inspecionar rastros usando a guia Call Chart

A guia Call Chart oferece uma representação gráfica do rastreamento de método ou função, em que o período e o tempo de uma chamada são representados no eixo horizontal e os recebedores de chamada são mostrados ao longo do eixo vertical. As chamadas para APIs do sistema são mostradas em laranja, as chamadas aos próprios métodos do app são mostradas em verde e as chamadas para APIs de terceiros, incluindo APIs da linguagem Java, são mostradas em azul. A Figura 4 mostra um exemplo de gráfico de chamadas e ilustra os conceitos de tempo próprio, tempo secundário e tempo total para um determinado método ou função. Saiba mais sobre esses conceitos na seção sobre como inspecionar rastros usando as guias Top Down e Bottom Up.

Figura 1. Exemplo de gráfico de chamadas que ilustra o tempo próprio, o secundário e o total para o método D.

Dica: para acessar o código-fonte de um método ou função, clique com o botão direito e selecione Jump to Source. Esse acesso funciona em qualquer guia do painel Analysis.

Inspecionar rastros usando a guia Flame Chart

A guia Flame Chart oferece um gráfico de chamadas invertido que agrega pilhas de chamadas idênticas. Ou seja, métodos idênticos que compartilham a mesma sequência de autores da chamada são coletados e representados como uma barra mais longa em um Flame Chart em vez de serem exibidos como várias barras mais curtas, como mostrado em um gráfico da chamada. Dessa forma, é mais fácil ver quais métodos ou funções consomem a maior quantidade de tempo. No entanto, isso também significa que o eixo horizontal não representa uma linha do tempo. Em vez disso, indica a quantidade relativa de tempo que cada método ou função leva para ser executado.

Para ajudar a ilustrar esse conceito, considere o gráfico de chamadas na Figura 2. Observe que o método D faz várias chamadas para B (B1, B2 e B3) e que algumas chamadas para B chamam C (C1 e C3).

Figura 2. Gráfico de chamadas com várias chamadas de método que compartilham uma sequência comum de autores de chamada.

Como B1, B2 e B3 compartilham a mesma sequência de autores de chamada (A → D → B), eles são agregados, como mostrado na Figura 3. De forma similar, C1 e C3 são agregados porque compartilham a mesma sequência de autores de chamada (A → D → B → C). Observe que C2 não é incluído porque tem uma sequência diferente de autores de chamada (A → D → C).

Figura 3. Agregação de métodos idênticos que compartilham a mesma pilha de chamadas.

As chamadas agregadas são usadas para criar o Flame Chart, como mostrado na Figura 4. Observe que, em qualquer chamada de um Flame Chart, os recebedores que consomem a maior parte do tempo de CPU são mostrados primeiro.

Figura 4. Representação do Flame Chart do gráfico de chamadas mostrado na Figura 5.

Inspecionar rastros usando Top Down e Bottom Up

A guia Top Down mostra uma lista de chamadas em que a expansão de um nó do método ou da função exibe os recebedores de chamadas. A Figura 5 mostra um gráfico da guia Top Down para o gráfico de chamadas na Figura 1. Cada seta no gráfico aponta de um autor para um recebedor da chamada.

Como mostrado na Figura 5, a expansão do nó do método A na guia Top Down exibe os recebedores de chamada, os métodos B e D. Depois disso, a expansão do nó do método D expõe os recebedores da chamada, os métodos B e C e assim por diante. De forma similar à guia Flame Chart, a árvore Top Down agrega informações de rastros para métodos idênticos que compartilham a mesma pilha de chamadas. Ou seja, a guia Flame Chart oferece uma representação gráfica da guia Top Down.

A guia Top Down fornece as informações a seguir para descrever o tempo de CPU gasto em cada chamada de método. Os tempos também são representados como porcentagem do tempo total da linha de execução em relação ao intervalo selecionado:

  • Self: a quantidade de tempo que a chamada do método ou da função levou para executar o próprio código, e não o código dos recebedores da chamada, como ilustrado no método D da Figura 1.
  • Children: a quantidade de tempo que a chamada do método ou da função levou para executar o código dos recebedores da chamada, e não o próprio código, como ilustrado no método D da Figura 1.
  • Total: a soma dos tempos Self e Children dos métodos. É a representação da quantidade total de tempo gasto pelo app ao executar uma chamada, conforme ilustrado na Figura 1 para o método D.

Figura 5. Uma árvore Top Down.

Figura 6. Uma árvore Bottom Up para o método C da Figura 5.

A guia Bottom Up mostra uma lista de chamadas em que a expansão de um nó do método ou da função exibe os autores da chamada. Usando o rastro de exemplo mostrado na Figura 5, a Figura 6 mostra uma árvore Bottom Up do método C. A abertura do nó para o método C na árvore Bottom Up mostra cada um dos autores da chamada exclusivos, os métodos B e D. Observe que, embora B chame C duas vezes, B é exibido apenas uma vez na expansão do nó para o método C na árvore Bottom Up. Depois disso, a expansão do nó B exibe os autores da chamada, os métodos A e D.

A guia Bottom Up é útil para classificar métodos de acordo com os que consomem mais (ou menos) tempo de CPU. Você pode inspecionar cada nó para determinar quais autores da chamada gastam mais tempo de CPU invocando esses métodos ou funções. Em comparação com a árvore de cima para baixo, as informações de tempo de cada método ou função em uma árvore de baixo para cima fazem referência ao método na parte superior de cada árvore (nó superior). O tempo de CPU também é representado como porcentagem do tempo total da linha de execução durante a gravação. A tabela a seguir ajuda a explicar como interpretar as informações de tempo do nó superior e dos respectivos métodos de autores da chamada (subnós).

Self Children Total
Método ou função na parte superior da árvore de baixo para cima (nó principal) Representa o tempo total que o método ou função levou para executar o próprio código, e não o de seus recebedores da chamada. Em comparação com a árvore de cima para baixo, essas informações de tempo representam uma soma de todas as chamadas para esse método ou função durante a gravação. Representa o tempo total que o método ou a função gastou executando o código dos recebedores da chamada, e não o próprio código. Em comparação com a árvore de cima para baixo, essas informações de tempo representam a soma de todas as chamadas para os recebedores da chamada desse método ou função durante a gravação. A soma dos tempos próprios e secundários.
Autores de chamadas (subnós) Representa o total do tempo próprio do recebedor da chamada quando chamado pelo autor. Usando a árvore Bottom Up da Figura 6 como exemplo, o tempo próprio para o método B seria a soma de todos os tempos próprios para cada execução do método C quando chamado por B. Representa o total do tempo secundário do recebedor da chamada quando invocado pelo autor. Usando a árvore Bottom Up da Figura 6 como exemplo, o tempo secundário para o método B seria a soma de todos os tempos secundários para cada execução do método C quando chamado por B. A soma dos tempos próprios e secundários.

Observação: para uma determinada gravação, o Android Studio deixa de coletar novos dados quando o criador de perfil alcança o limite de tamanho de arquivo. No entanto, a gravação continua. Normalmente, isso acontece muito mais rapidamente na execução de rastros instrumentados, já que esse tipo de rastro coleta mais dados em um período menor em comparação a um rastro por amostra. Se você ampliar o tempo da inspeção até conter um período da gravação após o limite ser alcançado, os dados de tempo no painel de rastros não vão mudar, porque não haverá novos dados disponíveis. Além disso, o painel de rastros exibirá NaN como informações de tempo quando você selecionar apenas a parte da gravação que não tem dados disponíveis.

Inspecionar traces usando a tabela de eventos

A tabela de eventos lista todas as chamadas atualmente na linha de execução selecionada. Para classificá-las, clique nos cabeçalhos das colunas. Ao selecionar uma linha na tabela, é possível navegar pela linha do tempo para os horários de início e término da chamada selecionada. Isso possibilita que você localize eventos com precisão na linha do tempo.

Figura 7. Visualização da guia "Events" no painel "Analysis".

Inspecionar frames da pilha de chamadas

As pilhas de chamadas são úteis para entender qual parte do código foi executada e por que ela foi invocada. Se um exemplo de gravação da pilha de chamadas for coletado para um programa Java/Kotlin, a pilha de chamadas vai incluir não só o código Java/Kotlin, como também frames do código nativo JNI, a máquina virtual Java (por exemplo, android::AndroidRuntime::start) e o kernel do sistema ([kernel.kallsyms]+offset). Isso ocorre porque um programa Java/Kotlin normalmente é executado em uma máquina virtual Java. O código nativo é necessário para executar o programa e para que ele se comunique com o sistema e o hardware. O criador de perfis apresenta esses frames para melhorar a precisão. No entanto, dependendo da investigação, você pode ou não considerar úteis esses frames de chamada extras. O criador de perfis oferece uma maneira de recolher os frames que não são interessantes para ocultar informações irrelevantes para sua investigação.

No exemplo abaixo, o trace tem muitos frames rotulados como [kernel.kallsyms]+offset, todos eles inúteis para o desenvolvimento atual.

Exemplo de rastro de chamada

Para recolher esses frames em um só, selecione o botão Collapse frames na barra de ferramentas, escolha os caminhos que vão ser recolhidos e selecione o botão Apply para aplicar as mudanças. Neste exemplo, o caminho é [kernel.kallsyms].

Exemplo de menu do Simpleperf

Assim, os frames correspondentes ao caminho selecionado serão recolhidos nos painéis esquerdo e direito, conforme mostrado abaixo.

Exemplo de frames recolhidos no Simpleperf

Inspecionar rastreamentos do sistema

Ao inspecionar um rastro do sistema, você pode examinar Trace Events na linha do tempo Threads para visualizar os detalhes dos eventos que ocorrem em cada linha de execução. Passe o cursor sobre um evento para ver o nome dele e o tempo gasto em cada estado. Clique em um evento para ver mais informações no painel Analysis.

Inspecionar rastreamentos do sistema: núcleos da CPU

Além dos dados de programação da CPU, os rastreamentos do sistema também incluem a frequência da CPU por núcleo. Isso mostra a quantidade de atividade em cada núcleo e pode dar uma ideia de quais deles são os núcleos "grandes" ou "pequenos" em processadores modernos para dispositivos móveis.

Figura 8. Visualização da atividade da CPU e eventos de trace para a linha de execução de renderização.

O painel CPU Cores, como mostrado na Figura 8, apresenta a atividade de linha de execução programada em cada núcleo. Passe o cursor do mouse sobre uma atividade da linha de execução para ver em qual linha esse núcleo está sendo executado nesse momento específico.

Para saber mais sobre como inspecionar informações de rastreamentos do sistema, consulte a seção Investigar problemas de desempenho da IU da documentação do systrace.

Inspecionar rastreamentos do sistema: linha do tempo de renderização do frame

Você pode inspecionar quanto tempo o app leva para renderizar cada frame na linha de execução principal e na RenderThread para investigar os gargalos que causam instabilidade da IU e baixas taxas de frames. Para aprender a usar rastreamentos do sistema para investigar e reduzir a instabilidade da IU, consulte Detecção de instabilidade da IU.

Inspecionar traces do sistema: Process Memory (RSS)

Para apps implantados em dispositivos com o Android 9 ou versões mais recentes, a seção Process Memory (RSS) mostra a quantidade de memória física atualmente em uso pelo app.

Figura 9. Visualização da memória física no criador de perfil.

Total

Essa é a quantidade total de memória física atualmente em uso pelo seu processo. Em sistemas baseados em Unix, isso é conhecido como "Tamanho do conjunto de residentes" e é a combinação de toda a memória usada por alocações anônimas, mapeamentos de arquivos e alocações de memória compartilhadas.

Para desenvolvedores do Windows, o "Tamanho do conjunto residente" é parecido com o "Tamanho do conjunto de trabalho".

Allocated

Esse contador rastreia a quantidade atual de memória física em uso pelas alocações normais de memória do processo. Essas alocações são anônimas (não protegidas por um arquivo específico) e particulares (não compartilhadas). Na maioria dos aplicativos, elas são compostas por alocações de heap (com malloc ou new) e memória de pilha. Quando trocados da memória física, essas alocações são gravadas no arquivo de troca do sistema.

File Mappings

Esse contador rastreia a quantidade de memória física que o processo está usando para mapeamentos de arquivos. Ou seja, a quantidade de memória mapeada dos arquivos pelo gerenciador de memória em uma região dela.

Shared

Esse contador rastreia a quantidade de memória física em uso para compartilhar memória entre esse e outros processos no sistema.