Tipos de perfil e quando cada um é útil

É possível gravar vários tipos de perfis de desempenho no Android. A coleta de um perfil ajuda a depurar problemas relacionados à velocidade de execução do app, à quantidade de memória usada, à quantidade de energia consumida e muito mais.

Este documento descreve os tipos de perfis mais úteis e quando usar cada um deles para depurar problemas comuns de desempenho.

Rastros do sistema

Exemplo de rastreamento do sistema
Figura 1: Exemplo de rastreamento do sistema.

Um rastreamento do sistema é um perfil avançado que contém informações sobre processos, linhas de execução, informações de tempo, execução de CPU e tarefas, além de eventos definidos pelo sistema ou pelo usuário.

Do ponto de vista de um app, a natureza das informações nos rastreamentos pode abranger uma ampla variedade de áreas, incluindo latência, instabilidade, memória, bateria e muito mais.

Os rastreamentos do sistema contêm os seguintes eventos orientados por código, que podem ser definidos pelo sistema ou pelo usuário. Os eventos baseados em código são aqueles que os usuários podem acionar por chamadas de função.

  • Intervalos de rastreamento: representam o tempo entre diferentes pontos no seu código. Elas podem ser adicionadas com as APIs Trace.beginSection e Trace.endSection.
  • Contadores de rastreamento: valores numéricos que representam métricas, por exemplo, tamanho do heap. Eles podem ser adicionados com a API Trace.setCounter.

Os rastreamentos do sistema também contêm métricas que podem ser criadas com consultas do PerfettoSQL e usadas para realizar análises ou comparar rastreamentos.

Recomendamos usar rastreamentos do sistema para realizar as seguintes tarefas:

  • Diagnosticar problemas de latência. Os rastreamentos do sistema são excelentes para encontrar problemas de latência causados por atrasos, esperas ou problemas de programação. Outros profilers, como os baseados em amostras, não fornecem as informações de tempo que os rastreamentos do sistema oferecem.

  • Encontre cálculos duplicados. O rastreamento pode revelar se determinados cálculos estão sendo repetidos, o que pode indicar operações desnecessárias.

  • Diagnosticar problemas de disputa de bloqueio. Com informações sobre estados de linhas de execução e intervalos que mostram quando os recursos estão bloqueados, é possível identificar se os bloqueios (como os synchronized) estão causando atrasos nas jornadas dos usuários.

  • Entenda a multithreading no seu app: os rastreamentos oferecem uma visão de várias linhas de execução, mostrando o estado de cada uma e os intervalos de rastreamento adicionados pelo sistema ou pelo app. Essa visualização multithread ajuda a entender quais linhas de execução estão ativas, em suspensão ou o que elas estão executando e como interagem.

  • Realizar análises de performance complexas. A interface do usuário avançada e a capacidade de mostrar vários tipos de informações tornam os rastreamentos do sistema úteis para depurar uma ampla variedade de problemas de desempenho, incluindo latência, memória e uso da bateria.

Os rastreamentos do sistema também podem ser consultados usando o PerfettoSQL. Com esse recurso poderoso, você pode:

  • Extrair dados específicos.
  • Transforme dados de rastreamento em métricas personalizadas.
  • Crie faixas de depuração com base em consultas para facilitar a visualização dos aspectos mais importantes na interface do Perfetto.
  • Realize análises complexas diretamente na interface do Perfetto.

Perfis de amostra de pilha

Exemplo de perfil de amostragem de pilha
Figura 2: Exemplo de perfil de amostra de pilha.

Os perfis de amostra de pilha funcionam gravando amostras de execução de código e armazenando as informações da pilha de chamadas a uma taxa definida enquanto uma linha de execução executa tarefas na CPU. Isso fornece insights sobre o que o código está fazendo durante a execução.

Recomendamos usar exemplos de pilha para fazer o seguinte:

  • Otimizar pontos de acesso. As amostras de pilha ajudam a identificar partes do código com muita atividade da CPU, o que significa que a linha de execução está frequentemente em um estado "em execução".
  • Entenda a execução do código. As amostras de pilha podem ajudar você a entender o comportamento geral da sua base de código.
  • Identifique o código que não deve ser executado. Você pode encontrar call stacks que não deveriam ter sido executadas, o que aponta para oportunidades imediatas de otimização.

Heap dumps

Exemplo de heap dump
Figura 3: Exemplo de heap dump.

Os despejos de heap do Java mostram um snapshot da memória de heap do Java do app. Esse snapshot inclui todos os objetos e como eles se referem uns aos outros no momento em que o despejo foi feito.

Recomendamos coletar despejos de heap para fazer o seguinte:

  • Descobrir objetos duplicados. Os despejos de heap mostram o número de objetos ativos, o que é útil para rastrear objetos duplicados. Elas também fornecem referências de objetos, ajudando a identificar o local do código em que os objetos foram criados.
  • Encontrar vazamentos de memória. Os despejos de heap podem revelar memória que não deveria mais estar em uso quando o despejo foi feito, indicando possíveis vazamentos de memória.
  • Identifique objetos que podem ser otimizados. Ao mostrar objetos que usam muita memória e suas contagens, os despejos de heap ajudam a identificar padrões de uso de memória ineficientes.

Perfis de alocação heap

Exemplo de perfil de heap
Figura 4: Exemplo de perfil de heap.

Os perfis de heap vêm nas versões nativa e Java e são excelentes para depurar problemas de memória. Eles são semelhantes às amostras de pilha de chamadas, mas, em vez de medir ciclos de CPU, coletam amostras quando a memória é alocada.

Recomendamos usar perfis de heap para fazer o seguinte:

  • Reduza a rotatividade de memória. Os perfis de heap fornecem amostras com locais de código para alocações de memória. Isso ajuda a identificar áreas que criam muitos objetos temporários, o que pode contribuir para coletas de lixo (GCs) frequentes no seu app.
  • Descobrir vazamentos de memória (em inglês). Os perfis de heap podem ser usados com outros perfis de memória para diagnosticar e corrigir vazamentos de memória. Elas ajudam a identificar locais que estão alocando muito mais memória do que o esperado.

Combinar perfis

Muitas vezes, você vai analisar a performance usando um único perfil. No entanto, coletar vários perfis ou um único perfil combinado geralmente fornece uma imagem mais completa e ajuda a diagnosticar problemas complexos que um único perfil não consegue.

Considere estes cenários em que a combinação de perfis é benéfica:

  • Cenário 1: investigar código não instrumentado. Um rastreamento do sistema pode mostrar a latência das operações que você já instrumentou. No entanto, talvez você precise de mais informações sobre partes não instrumentadas do código em execução durante esses períodos. Para investigar, faça um perfil de pilha de chamadas para entender o código executado. Essas informações podem ajudar você a melhorar o rastreamento adicionando mais partes.

  • Cenário 2: análise de vazamentos de memória e coletas de lixo. Imagine que um rastreamento do sistema mostre um aumento constante na memória de heap do Java devido a alocações, o que aciona coletas de lixo (GCs) frequentes. Para entender os objetos alocados, faça um perfil ou um despejo de heap. Essa abordagem combinada ajuda a identificar maneiras de reduzir o uso da memória. Por exemplo, reduzir alocações desnecessárias ou otimizáveis usando o cache pode evitar que as GCs ocorram.