A otimização de apps Android exige uma visibilidade profunda dos fluxos de trabalho simultâneos e das suspensões de corrotinas.
Embora a criação de perfis local ofereça um resumo útil, escalonar esses insights para a produção sem sobrecarga continua sendo um desafio.
Esta sessão apresenta um modelo arquitetônico para um ciclo de feedback de desempenho contínuo.
androidx.tracing 2.0: troca back-ends dinamicamente e propaga contextos de corrotina (fluxos do Perfetto) entre linhas de execução.
Instrumentação inteligente: use o rastreamento local do ART para encontrar pontos de acesso e automatize a injeção de pontos de rastreamento de baixa sobrecarga.
Macrobenchmark: acompanhe regressões e verifique ganhos de desempenho em dispositivos físicos na CI.
Rastreamento de campo: vá além do rastreamento local e de CI com o ProfilingManager.
traceCoroutine ou transmitir tokens de propagação para o código baseado em callback.Transcrição
Rahul Ravikumar
Olá, pessoal.
Meu nome é Rahul.
Sou engenheiro na equipe de experiência do desenvolvedor Android.
Meu foco é o desempenho de apps e bibliotecas, e esta palestra é sobre rastreamento.
Antes de nos aprofundarmos no rastreamento, quero estabelecer um vocabulário compartilhado para que você possa acompanhar.
Portanto, sempre que eu me referir ao rastreamento nesta palestra, estarei falando sobre o rastreamento explícito, que é a instrumentação manual do código para que você saiba o que o app está fazendo.
Não estou falando de criadores de perfil automáticos, que vou abordar mais adiante.
O rastreamento manual é a arte de deixar migalhas de pão na base de código para que você possa entender o que aconteceu quando tiver um problema de desempenho ou qualquer outro problema.
Geralmente, é muito melhor do que os registros.
Não sei se você já viu uma saída do Logcat de um app grande.
Geralmente, é um bloco gigante de texto que não é fácil de entender.
O rastreamento, por outro lado, é muito melhor.
É mais fácil de visualizar.
Você tem durações.
Você tem uma estrutura.
Você tem algumas ferramentas para analisar os dados e ver exatamente o que aconteceu e quando.
Por isso, é muito melhor.
E você pode, sabe, apontar seus agentes para um trace e fazer perguntas.
Você pode usar ferramentas como o Processador de Trace, comparativos de mercado e até mesmo converter seus traces em métricas.
Essas são todas as coisas que você pode fazer com os traces que são difíceis de fazer com o Logcat.
Por outro lado, a criação de perfis, e estou falando da criação automática de perfis, geralmente é uma resposta a um problema que você conhece.
Por exemplo, você pode ter notado que o app inicia lentamente ou que algo está travando e quer descobrir o que está acontecendo.
Se você não tiver traces manuais para ajudar, é aí que entra a criação de perfil automática.
Você pode usar algo como o rastreamento de método do ART, em que cada entrada e saída de método é instrumentada.
Ou talvez você esteja analisando a amostragem de pilha com ferramentas como o Simpleperf.
Portanto, em vez de usar cada entrada e saída de método e ter uma sobrecarga alta, você analisa as amostras da pilha de chamadas e vê o que está no caminho crítico do app.
Estamos em 2026, a RAM é um problema em todos os lugares, então você pode estar analisando a memória, os vazamentos de memória e os perfis de heap.
Esse é mais um criador de perfil que você pode usar.
Você pode analisar os caminhos de retenção de heap.
Você pode ver qual código está alocando memória, e esses são todos os tipos de análise que você pode fazer com isso.
Certo.
Agora, temos esse vocabulário.
Agora vamos falar sobre por que criamos uma nova biblioteca.
As APIs de rastreamento 1.0 foram introduzidas no Android Jelly Bean.
Isso foi em 2012.
Isso foi há mais de 14 anos.
Desde então, as APIs não evoluíram tanto quanto você imagina.
Adicionamos algumas extensões.
Os eventos e contadores assíncronos foram adicionados no Android 10.
Isso foi em 2019.
E só.
A API não evoluiu desde então.
No entanto, o ecossistema evoluiu bastante.
O rastreamento da plataforma melhorou muito, mas nada disso se refletiu em adições de API para você.
Queremos mudar isso.
O outro grande problema é que o rastreamento tem um back-end fixo na versão 1.0. Isso significa que, sempre que você adiciona uma seção de rastreamento ao código, ela sempre acaba no buffer de rastreamento do sistema.
O Atrace é o subsistema de rastreamento do Android que possui esses dados.
Portanto, se você quiser pegar seus traces e convertê-los em telemetria de campo, isso é muito difícil, porque, primeiro, você precisa entender como o atrace armazena esses dados.
É um formato bem documentado, mas que pode ser difícil de consumir.
Isso é algo que queremos corrigir.
Por isso, queremos oferecer as ferramentas para você levar seus dados de rastreamento para onde quiser.
Também havia uma restrição no Tracing 1.0 em que os rótulos eram limitados a 128 caracteres.
Essa era uma restrição razoável em 2012, mas em 2026, parece um pouco estranha.
Para piorar, também não é possível adicionar metadados extras ao trace, o que é ainda mais problemático.
E há também a sobrecarga.
Portanto, sempre que você estiver rastreando seu app, é preciso estar extremamente ciente do overhead, porque o ato de observar um sistema não deve mudar o que o sistema está fazendo em segundo plano.
Portanto, se houver uma disputa que você queira reproduzir, o rastreamento não deve fazer com que ela desapareça.
Portanto, é importante preservar toda a semântica que você está usando.
O Tracing 1.0 tinha uma sobrecarga relativamente alta, e queríamos melhorar isso.
Ok.
Falei muito sobre os problemas.
Agora, vamos analisar alguns dos problemas visualmente e ver como eles se agravam na prática.
Aqui temos um rastro do Perfetto.
É para um app, com.example.app.
Temos uma linha de execução principal e uma única fração chamada initializeComponent.
Agora, o ideal é que tenhamos mais detalhes.
Vamos adicionar um detalhe.
Agora sabemos que initializeComponent chama performInitialize.
Ainda não sabemos qual componente está sendo inicializado.
Agora, a única ferramenta no nosso cinto de utilidades com o Tracing 1 é o nome, então vamos adicioná-lo ao nome da fração.
Lembre-se de que os nomes de frações de rastreamento são restritos a 128 caracteres, então eles são truncados no rastreamento.
Para piorar, o overhead de truncamento agora também é um overhead que você tem ao fazer o rastreamento.
Agora, você se depara com esse problema rapidamente.
Então, queríamos muito corrigir isso.
Você viu o rastro do Perfetto e como ele é visualmente.
Agora, vamos analisar a perspectiva de escrever o código para emitir essas seções de trace.
Novamente, temos a API initializeComponent.
Ela usa um contexto e um nome e chama performInitialize.
Até aqui, tudo bem.
Agora, queremos adicionar um trace com a API Tracing 1.0. Para isso, importe androidx.tracing.trace e use um bloco de trace.
Dê um nome a ela.
Aqui, é performInitialize.
Mas, como queríamos fazer antes, queremos saber o nome do componente. Por isso, vamos usar a interpolação de strings do Kotlin e adicionar o nome.
E aqui está o primeiro problema.
Aqui temos o limite de 128 caracteres.
Rahul Ravikumar
Podemos corrigir isso com o Tracing 2.
Em vez de usar androidx.tracing.trace, use Tracer.
A API é muito parecida.
Em vez de trace, você tem Tracer.global.trace.
Você tem uma categoria.
Vamos falar sobre as categorias em mais detalhes depois, mas, basicamente, você tem um nome.
E, em seguida, você ainda tem o bloco de código que está tentando rastrear.
E agora, você não tem mais a limitação de 128 caracteres.
Falei sobre a sobrecarga de rastreamento.
Quero entrar em mais detalhes e ver como melhoramos isso.
Em um Pixel 6a com o Android 16, o ato de inserir uma única seção de início e fim levou cerca de 1.200 nanossegundos.
Isso pode não parecer muito, mas se você tiver um código muito quente que está adicionando muitas seções de trace, esse é um tempo que o app poderia estar gastando na renderização de frames.
Por isso, não queremos tomar seu tempo.
Na verdade, melhoramos bastante as coisas com o SDK do AndroidX Perfetto.
Esse era um SDK experimental que introduzimos para o Composition Tracing, e ele melhorou muito a situação.
Não queríamos que você fizesse isso porque esse é o SDK do Perfetto C com vinculações JNI, e o SDK do C tem cerca de 4 MB no APK.
Não queríamos que você enviasse isso.
Agora, com o Tracing 2, temos uma biblioteca criada para essa finalidade.
Melhoramos muito mais a sobrecarga, e agora você vai gostar de saber que o Tracing 2 é sete vezes mais rápido, o que significa que você tem mais tempo para fazer o que quer, e a infraestrutura leva menos tempo.
O que isso possibilita que não era possível antes?
Um exemplo é o recurso de rastreamento de ambiente de execução do Metro.
O Metro, para quem não sabe, é uma biblioteca de injeção de dependência.
Ele é compatível com o Kotlin Multiplatform.
Ele usa um plug-in do compilador Kotlin.
Ele gera todo o código para injeção de dependência e se integra ao Tracing 2.0 para facilitar a visualização do custo de cada @Inject no seu código.
Veja um exemplo.
Digamos que temos um gráfico de app.
No Metro, tudo tem o escopo de um gráfico, então temos um único campo, AnalyticsTracker.
Também temos uma vinculação de fornecimento.
Temos um cliente de rede com o OkHttpClient como impl, e a implementação de AnalyticsTracker vem do AnalyticsTrackerImpl. Precisamos de uma instância do cliente de rede, que o gráfico sabe como fornecer.
Por trás dos panos, o plug-in do compilador gera um código parecido com este.
Portanto, se você tiver o AnalyticsTracker, o getter vai criar uma instância do cliente de rede e transmiti-la ao construtor de AnalyticsTrackerImpl, o que é bom.
Mas agora, com o rastreamento ativado, é possível ver o custo de criação não apenas da impl do rastreador, mas de cada dependência necessária.
Agora, é possível ver não apenas o custo de instanciar o tipo, mas também todas as dependências dele em um rastro, o que é muito útil.
Usando essas informações, o Wise, que é um app de finanças, melhorou a inicialização em 45%.
Eles conseguiram adiar coisas que não eram necessárias para inicializar durante a inicialização do app e também identificaram alguns itens com escopo incorreto, em que coisas que deveriam ter sido um singleton não eram realmente singletons por acidente, e essas são coisas que você pode ver e corrigir facilmente no seu código.
Se você analisar as métricas de inicialização, elas são realmente impressionantes.
Além de melhorar o tempo até o frame inicial, eles também melhoraram o tempo até a exibição completa.
Outro parceiro, o BandLab, usa as mesmas informações sobre CI.
Assim, você não só sabe o custo de cada vinculação @Inject, mas também qual linha de execução gerou esse custo.
Depois de saber disso, você pode encontrar todas as vinculações @Inject caras na linha de execução principal e, na CI, executar uma consulta para receber uma lista de todas as vinculações caras e atribuí-las à mudança que as introduziu. Assim, você pode identificar a mudança real e tentar corrigi-la.
Rahul Ravikumar
Ok.
Até agora, falei sobre todas as melhorias que fizemos em relação ao Tracing 1, mas agora vou falar sobre os novos recursos do Tracing 2 que nunca foram possíveis antes.
Um dos recursos principais é chamado de propagação de contexto. Como os apps modernos estão cada vez mais complexos, as cargas de trabalho são executadas em várias linhas de execução, corrotinas e processos.
Você quer visualizar como uma solicitação se propaga entre cada linha de execução e processo.
E é isso que a propagação de contexto possibilita.
Se eu apenas fornecesse uma lista de fatias sem explicar o que causou o quê, elas seriam úteis, mas não seriam fáceis de entender.
Mas se eu disser que essa foi a cadeia causal de eventos, vai ser muito mais fácil descobrir o que estava acontecendo e associar o custo de cada fração.
É isso que a propagação de contexto disponibiliza.
A propagação de contexto é totalmente compatível. Veja um exemplo real.
Voltando ao rastro do Perfetto de com.example.app, digamos que performInitialize estava demorando muito e você queria adiar o custo ou movê-lo para uma linha de execução diferente.
Você consegue fazer isso.
Digamos que eu tenha movido performInitialize para outra conversa.
Agora, você perdeu a natureza hierárquica da fração.
Agora, não é mais possível saber que initializeComponent foi o que causou performInitialize, a menos que você olhe o código.
Em um mundo ideal, você gostaria de uma seta para indicar que A causou B e, em seguida, poder raciocinar sobre a cadeia causal de eventos.
Talvez você já tenha visto um rastreamento do sistema em que fazemos isso para transações de binder na plataforma.
Aqui, você pode ver que o comparativo de mercado do Compose faz uma transação de binder para system_server para preparar um frame.
Isso sempre foi possível do ponto de vista do rastreamento da plataforma, mas nunca disponibilizamos as ferramentas para desenvolvedores de apps.
Agora, a propagação de contexto de corrotina do Kotlin é totalmente compatível com o Tracing 2.0.
Não é necessário fazer nada.
Você já recebe tudo pronto para uso.
Aqui, temos um único método de suspensão chamado fetchProfile.
Ele chama um client.get, que é outro método de suspensão, e depois muda para Dispatchers.Default para desserializar a resposta.
É um código de corrotinas bem comum, algo com que você provavelmente lida todos os dias.
Agora, digamos que queremos rastrear isso.
Adicionamos uma seção de trace.
Aqui, em vez de trace, vamos usar a API traceCoroutine, já que é um bloco de código de suspensão. Depois, para a chamada interna antes de alternar o contexto para Dispatchers.Default, vamos adicionar outra seção de trace interna usando a mesma API traceCoroutine.
Agora, em um trace, você verá algo assim.
Você vai notar que o trabalho começou no worker-1 e, em seguida, mudou de contexto e foi para o worker-3. Você vai ver setas úteis no rastro que indicam isso.
Além disso, se você ampliar o quadrado no meio, vai notar que a desserialização começou no worker-1, e a chamada para withContext foi o que causou a troca de contexto. Depois, ela continuou no worker-3, e fetchProfile foi retomado no worker-3 porque o mecanismo de corrotinas quer minimizar o número de trocas de contexto que acontecem.
É possível ver exatamente quando uma corrotina foi suspensa, quando foi retomada e a cadeia causal completa de eventos.
Outra possibilidade do Tracing 2 é adicionar metadados personalizados a um trace.
No passado, a única ferramenta disponível era o nome da seção de trace, mas agora você pode adicionar um bloco de metadados que permite incluir quantas entradas de metadados quiser.
E você pode adicionar isso ao trace.
Ao analisar o trace real, é possível ver que todos os metadados adicionados estão no trace para que todas as ferramentas os consumam e usem.
Agora, você pode incorporar tudo o que sabe, todas as informações adicionais que sempre quis.
Então, eu mostrei vários recursos abstratos que o rastreamento possibilita, mas o que realmente se destaca é um novo recurso no Jetpack Compose chamado rastreamento de recomposição.
Isso é enviado como parte do Compose 1.13, então já está pronto para uso.
Veja um exemplo.
Este é o rastreamento de composição, que vocês provavelmente já conhecem.
Isso existe desde os primórdios do Compose.
Ele informa o custo relativo de um elemento combinável e de todas as, você sabe, subfatias dele, além do custo de cada uma na linha de execução em que estavam ocorrendo.
É bem simples.
O que ele não diz é o contexto.
Ele não informa o motivo.
Ele não informa o motivo da recomposição.
Se eu diminuir o zoom, essa é a região de interesse que acabamos de ver no slide anterior.
À esquerda, é possível ver que ocorreu um evento de entrada de envio.
Talvez isso tenha mudado algum estado e causado a recomposição.
Mas não está claro.
Você não tem certeza.
No entanto, com o rastreamento de recomposição, agora adicionamos metadados personalizados ao rastreamento que informam exatamente por que as recomposições aconteceram.
Além disso, agora é muito fácil perceber que esses eventos estão relacionados.
Se você clicar neles, vai saber exatamente qual estado mudou.
Ele vai informar que era um estado, um valor de estado mutável que foi alterado para falso, que antes era verdadeiro.
Além disso, vamos informar a pilha de chamadas exata que causou o problema.
Aqui, você pode ver que AbstractClickableNode.performClick aconteceu, o que fez com que o estado mutável mudasse, o que causou a recomposição.
Isso é muito legal, algo que não podíamos fazer antes.
Essas ferramentas também estão disponíveis, ou melhor, todas essas funcionalidades também estão disponíveis na nova ferramenta Android Performance Analyzer, se você quiser testar algumas das ferramentas de agente.
E à direita.
Eu disse que a propagação de contexto é totalmente compatível com as corrotinas do Kotlin.
Mas e quanto ao código que usa uma mistura de corrotinas e código sem corrotinas, ou talvez você esteja executando linhas de execução por conta própria, ou talvez tenha algum código brownfield muito antigo que usa callbacks por algum motivo?
Ok.
A boa notícia é que você ainda pode aproveitar todos os benefícios da propagação de contexto.
Digamos que temos uma API brownfield que usa um callback e um executor.
A implementação usa executor.execute, chama runCatching, que é o detalhe da implementação, recebe a resposta e, em seguida, informa o callback sobre a resposta.
Ok.
Agora, se eu quiser rastrear isso, vou usar Tracer.global.trace, dar um rótulo e cercar o bloco.
Mas, como também quero preservar a cadeia causal de eventos, vou aceitar um novo tipo opcional, chamado de token de propagação.
Vou transmitir o token para a API de trace interna.
Assim, quem chamar esse método pode, opcionalmente, me dar o token de propagação para que eu possa preservar a cadeia causal de eventos que acontecem.
Ok.
Agora, o autor da chamada dessa API pode ser uma API de suspensão.
Aqui, tenho uma função de suspensão profileRequest, que vai chamar a API que usa um callback e um executor.
Aqui, como estou conectando dois mundos, o de suspensão e o de callback, vou usar o builder suspendCoroutine.
Vou receber uma continuação, invocar a API e retomar a continuação no callback assim que receber a resposta.
E aqui está o executor que estou definindo, chamado profileRequestContext.
É um executor de linha de execução única.
Como o traceCoroutine incorpora um token de propagação no contexto da corrotina, posso obter o token de propagação de dentro do contexto da corrotina e transmiti-lo como entrada para a API brownfield, preservando a cadeia causal de eventos.
E no trace, isso fica muito óbvio.
Aqui, temos algo que começou no worker-3 e mudou para o executor de linha de execução única, depois que fizemos a troca de contexto, e depois voltou para o worker.
É bem legal.
Rahul Ravikumar
Ok.
Outra coisa que você pode fazer é personalizar o Tracer.global.
Até agora, a API Tracing 2.0 oferece padrões muito bons para o que Tracer.global precisa ser, mas, se você quiser personalizar, é possível.
Além disso, o Tracing 2.0 é compatível com a JVM e o Android, porque queremos que o rastreamento seja totalmente compatível com as bibliotecas Java e Android.
As três etapas para inicialização são: criar um coletor de trace.
Um coletor de trace é, na verdade, como os pacotes de trace são armazenados.
Ele define o formato de transmissão e o local dos traces de saída em que eles são armazenados.
Oferecemos uma implementação pronta para uso de um coletor de rastreamento que oferece suporte ao formato Perfetto, mas você pode criar seu próprio coletor de rastreamento.
Isso volta à tentativa de resolver o problema de que o atrace era o único back-end disponível no Tracing 1.
Queríamos corrigir isso.
Portanto, agora, se você quiser escrever um coletor do OpenTelemetry ou trazer seu próprio coletor, isso é totalmente possível.
Você pode optar por substituir isso.
Depois de ter um coletor, você pode criar um driver de trace e atribuir o coletor a ele.
E também é possível escolher quais categorias você quer ativar.
É aqui que as categorias realmente se destacam.
Assim, você pode decidir que, na versão, algumas categorias são mais importantes do que outras, em comparação com a depuração, e pode dizer que essas são as categorias que você quer ativar.
Ou você também pode dizer: "Quero ativar todas as categorias, independentemente de onde elas vieram".
E não tem problema nenhum nisso.
Também é possível adicionar atributos personalizados que são globais ao seu trace.
Assim, é possível incorporar itens como a versão do build, o tipo ou qualquer outro metadado que você queira anexar a um trace usando a API addAttribute.
Por fim, registre um rastreador chamando setGlobalTracer.
É isso que vincula Tracer.global a essa instância do rastreador e, consequentemente, é isso que está disponível para o processo.
No Android, como os processos têm um ciclo de vida muito mais bem definido, basta implementar AbstractTraceDriver.Factory, substituir o método create e fazer exatamente o que você fez antes.
Então, você cria o coletor e, em seguida, o driver.
Não é necessário se registrar aqui.
Vamos fazer o registro para você, porque sabemos que isso é o que aconteceu primeiro.
Ok.
Quero reiterar que o rastreamento está pronto para várias plataformas.
Essa é uma escolha intencional, porque sabemos que o Compose é executado em várias plataformas e queremos que seja possível fazer o rastreamento no maior número possível de lugares.
Hoje, oferecemos suporte ao Android e à JVM, mas nossa implementação deixa totalmente aberta a possibilidade de oferecer suporte a plataformas futuras, se quisermos.
Rahul Ravikumar
Você vai gostar de saber que o R8, a ferramenta usada para reduzir e otimizar o código-fonte no Android, usa o Tracing 2.0.
E, aproveitando os traces, otimizamos o R8 para reduzir e otimizar seu código 25% mais rápido.
Isso significa tempos de compilação mais curtos e, você sabe, tempos de espera mais curtos para as passagens de otimização.
Não vou falar sobre todas as otimizações que fizemos no R8, mas quero falar sobre uma delas para dar uma ideia do que o rastreamento possibilita.
O R8 é, essencialmente, um transformador de código-fonte para código-fonte.
Assim, você recebe um monte de JARs, reduz e otimiza eles e produz outro conjunto de JARs que podem ser dexados.
Aqui, o AGP começa lendo os JARs, que não são apenas o app, mas também todas as dependências dele.
Por isso, ele usa workers do Gradle para começar a ler todos os JARs de entrada.
Você tem muitos arquivos JAR que quer ler.
Depois de ler os JARs, o R8 começa a analisar o código e a criar um modelo do que ele representa, além de todos os pontos de entrada, para que possa começar a otimizar e reduzir o código.
Essa é a fração, await, que representa quando o R8 está realmente pronto para iniciar o processo de otimização, certo?
Talvez você perceba um espaço morto no meio e se pergunte por que temos esse tempo de CPU não utilizado.
Isso acontece porque, na API antiga, esperávamos que todos os workers lessem todos os arquivos antes de analisar qualquer coisa.
É claro que podemos corrigir isso, e foi exatamente o que fizemos.
No AGP 9, assim que terminamos de ler os JARs de entrada, começamos a processá-los imediatamente.
E não precisamos esperar que todos os workers terminassem de ler as entradas.
Isso reduziu bastante o tempo de espera para ler todas as entradas.
Essa é uma otimização óbvia que você pode ver em um rastro, mas não é tão óbvia quando você está apenas olhando para o código-fonte para ver o que vale a pena otimizar.
Outra ferramenta que usamos todos os dias como engenheiros do AndroidX é o Metalava.
O Metalava é uma ferramenta que usamos para garantir que as APIs que enviamos tenham as garantias de compatibilidade que você espera e sejam totalmente utilizáveis por pessoas externas sem os problemas que queremos evitar.
Essa ferramenta é executada em todas as APIs públicas e restritas. Portanto, qualquer tempo economizado aqui é, na verdade, tempo que recuperamos como engenheiros do AndroidX.
O Metalava também usou o rastreamento para melhorar os tempos de pós-envio em impressionantes 15%.
E, ao analisar o trace para explicar o que aconteceu, o Metalava executa dois tipos de verificação: a primeira verifica as APIs restritas, e a segunda verifica as APIs públicas.
Mas talvez você esteja percebendo um padrão.
Estamos fazendo uma série de configurações para executar essas verificações duas vezes.
Então, o que acontece é que todas as entradas do programa são lidas, criamos a PSI, que é a interface de estrutura do programa, ou seja, exatamente o formato do seu código que pode ser analisado.
Em seguida, criamos a AST antes de começar a aplicar todas as verificações de lint que queremos.
E estamos fazendo esse trabalho caro duas vezes.
Como corrigimos isso?
Fizemos isso apenas uma vez.
Então, em vez de fazer todo esse trabalho de configuração duas vezes, fizemos apenas uma vez e reutilizamos essas entradas para as verificações restritas e públicas, o que resultou em todas essas economias.
Sim.
Ok.
Rahul Ravikumar
Agora que você já tem uma ideia do que o Tracing 2.0 possibilita, é importante saber que, embora o rastreamento seja importante, saber o que rastrear é igualmente importante.
Não é bom espalhar traces por toda parte.
É preciso ter muito cuidado com o que você escolhe, e vou tentar dar algumas diretrizes sobre o que vale a pena rastrear.
A primeira coisa que você deve fazer é encontrar lacunas inexplicáveis no trace.
Portanto, sempre que as linhas de execução estiverem em estado de execução ou executável e você notar lacunas óbvias no rastreamento do sistema, sem conseguir entender o motivo ou o que o app está fazendo, talvez seja interessante investigar.
Nesse ponto, posso fazer um rastreamento de método sobreposto ao rastreamento do sistema e ver o que vale a pena rastrear. Depois, posso adicionar essas seções de rastreamento relevantes.
Também é importante priorizar as jornadas do usuário.
Portanto, você quer analisar a inicialização do app.
Você quer analisar as principais jornadas do usuário no app e descobrir se é possível explicá-las analisando um trace.
Portanto, sempre que você não conseguir entender algo, vale a pena rastrear.
Você também deve analisar pilhas de chamadas profundas ou o uso inexplicável da CPU em um trace e tentar descobrir exatamente o que está acontecendo. Em seguida, converta essas partes da base de código em traces.
Por isso, é possível rastreá-los.
E, sempre que as linhas de execução estiverem em suspensão, você precisa entender o motivo.
Elas devem estar aguardando uma E/S, uma transação de binder ou alguns eventos de entrada externos que você espera que aconteçam.
Mas se você tem, sabe, sono inexplicável, então vale muito a pena investigar, porque obviamente pode haver algo oculto ali.
Depois de adicionar as seções de trace no código, converta-as em comparativos de mercado para acompanhar as mudanças.
Assim, conforme sua base de código evolui, você pode ver se as métricas estão mudando, se os painéis realmente refletem grandes mudanças, porque assim você sabe que algo importante mudou.
Ou você pode pular todas as etapas anteriores e deixar que o agente faça isso.
Pegue essas diretrizes, transforme-as em uma habilidade, aponte seu agente favorito para ela e deixe que ele faça o trabalho.
Sim.
Rahul Ravikumar
Se eu convenci você de que o rastreamento é uma atividade que vale a pena e que você deve fazer, aqui está a configuração do projeto.
Isto é bem objetivo.
O rastreamento é apenas uma biblioteca Java tradicional, então você define uma dependência em androidx.tracing:tracing-wire, que é o driver de rastreamento compatível com o Perfetto e o combo de rastreamento, e a versão estável atual é a 2.0.5.
Se você usa uma biblioteca Java, é exatamente a mesma coisa. Novamente, essa é uma API totalmente multiplataforma.
Queremos estendê-lo a outras plataformas quando fizer sentido.
E sim, eu só queria fazer uma recapitulação rápida.
Então, eu falei sobre todos esses novos recursos legais que adicionamos.
Portanto, a propagação de contexto é muito, muito poderosa.
Podemos incorporar informações personalizadas, metadados, informações da pilha de chamadas e todos os tipos de outras coisas.
Não falei sobre muitas coisas.
É claro que você pode mudar o formato do trace, o coletor de trace e, por exemplo, levar os dados de trace para o OpenTelemetry.
Você pode fazer tudo isso.
O rastreamento é multiplataforma.
Essa é uma decisão muito consciente, porque queremos que o maior número possível de pessoas possa aproveitar esse recurso.
E todas as ferramentas que enviamos, seja o Perfetto, os comparativos de mercado do AndroidX, o novo analisador de desempenho ou o antigo Android Profiler, todas elas são compatíveis com o Tracing 2.0.
Agradecemos sua atenção.
Espero que você aproveite o Dev Summit. Até mais!