Se acalmem e vamos explicar mais sobre a performance.
Este é o terceiro dia da Semana de Destaque da Performance. Hoje, vamos continuar compartilhando detalhes e orientações sobre áreas importantes do desempenho do app. Vamos abordar a otimização guiada por perfil, melhorias de performance do Jetpack Compose e considerações sobre o trabalho nos bastidores. Vamos começar.
Otimização guiada por perfil
Os perfis de referência e os perfis de inicialização são fundamentais para melhorar o desempenho de inicialização e de execução de um app Android. Elas fazem parte de um grupo de otimizações de performance chamado otimização guiada por perfil.
Quando um app é empacotado, o dexer d8 usa classes e métodos e preenche os arquivos classes.dex do app. Quando um usuário abre o app, esses arquivos DEX são carregados, um após o outro, até que o app possa ser iniciado. Ao fornecer um perfil de inicialização, você informa ao d8 quais classes e métodos devem ser incluídos nos primeiros classes.dex arquivos. Essa estrutura permite que o app carregue menos arquivos, o que melhora a velocidade de inicialização.
Os perfis de referência movem as etapas de compilação Just in Time (JIT) dos dispositivos dos usuários para as máquinas dos desenvolvedores. O código compilado gerado com antecedência (AOT, na sigla em inglês) comprovadamente reduz o tempo de inicialização e os problemas de renderização.
Trello e perfis de referência
Perguntamos aos engenheiros do app Trello como os perfis de referência afetaram a performance do app. Depois de aplicar perfis de referência à principal jornada do usuário, o Trello teve uma redução significativa de 25 % no tempo de inicialização do app.
O Trello conseguiu melhorar o tempo de inicialização do app em 25 % usando perfis de referência.
Perfis de referência na Meta
Além disso, engenheiros da Meta publicaram recentemente um artigo sobre como estão acelerando os apps Android com perfis de referência.
Nos apps da Meta, as equipes observaram uma melhoria de até 40 % em várias métricas importantes depois de aplicar os perfis de referência.
Melhorias técnicas como essas também ajudam a aumentar a satisfação do usuário e o sucesso dos negócios. Compartilhar isso com seus proprietários de produtos, CTOs e tomadores de decisão também pode ajudar a acelerar a performance do app.
Começar a usar os perfis de referência
Para gerar um perfil de referência ou de inicialização, escreva um teste de macrobenchmark que exercite o app. Durante o teste, os dados de perfil são coletados e usados durante a compilação do app. Os testes são escritos usando a nova API UiAutomator, que vamos abordar amanhã.
Escrever um comparativo de mercado como esse é simples, e você pode conferir o exemplo completo no GitHub (link em inglês).
@Test fun profileGenerator() { rule.collect( packageName = TARGET_PACKAGE, maxIterations = 15, stableIterations = 3, includeInStartupProfile = true ) { uiAutomator { startApp(TARGET_PACKAGE) } } }
Considerações
Comece escrevendo um perfil de referência de testes de macrobenchmark e um perfil de inicialização para o caminho mais percorrido pelos usuários. Isso significa o principal ponto de entrada que os usuários usam para acessar seu app, que geralmente é depois de fazer login. Em seguida, continue escrevendo mais casos de teste para capturar uma imagem mais completa apenas para perfis de referência. Não é necessário cobrir tudo com um perfil de referência. Use os caminhos mais usados e meça a performance no campo. Vamos falar mais sobre isso na postagem de amanhã.
Começar a usar a otimização guiada por perfil
Para saber como os perfis de referência funcionam, assista a este vídeo da Android Developers Summit:
Confira também o episódio do Android Build Time sobre otimização orientada por perfil para mais detalhes:
Também temos orientações abrangentes sobre Perfis de referência e Perfis de inicialização para você ler mais.
Melhorias de desempenho do Jetpack Compose
O investimento em desempenho da equipe de engenharia no framework de UI para Android deu certo. Desde a versão 1.9 do Jetpack Compose, a instabilidade de rolagem caiu para 0,2 % durante um teste comparativo interno de rolagem longa.
Essas melhorias foram possíveis devido a vários recursos incluídos nas versões mais recentes.
Janela de cache personalizável
Por padrão, os layouts lentos só compõem um item com antecedência na direção da rolagem, e depois que algo rola para fora da tela, ele é descartado. Agora é possível personalizar a quantidade de itens a serem mantidos usando uma fração da janela de visualização ou do tamanho em dp. Isso ajuda o app a realizar mais trabalho antecipadamente e, depois de ativar a composição pausável entre frames, usar o tempo disponível de maneira mais eficiente.
Para começar a usar janelas de cache personalizáveis, crie uma instância de LazyLayoutCacheWindow e transmita para sua lista ou grade lazy. Meça a performance do app usando diferentes tamanhos de janela de cache, por exemplo, 50% da janela de visualização. O valor ideal depende da estrutura do conteúdo e do tamanho do item.
val dpCacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)
val state = rememberLazyListState(cacheWindow = dpCacheWindow)
LazyColumn(state = state) {
// column contents
}Composição pausável
Com esse recurso, é possível pausar as composições e dividir o trabalho em vários frames. As APIs foram lançadas na versão 1.9 e agora são usadas por padrão na versão 1.10 na pré-busca de layout lento. Você vai notar mais benefícios com itens complexos que têm tempos de composição mais longos.
Mais otimizações de desempenho do Compose
Nas versões 1.9 e 1.10 do Compose, a equipe também fez várias otimizações um pouco menos óbvias.
Várias APIs que usam corrotinas internamente foram melhoradas. Por exemplo, ao usar Draggable e Clickable, os desenvolvedores vão notar tempos de reação mais rápidos e contagens de alocação aprimoradas.
As otimizações no rastreamento de retângulos de layout melhoraram a performance de modificadores como onVisibilityChanged() e onLayoutRectChanged(). Isso acelera a fase de layout, mesmo quando essas APIs não estão sendo usadas explicitamente.
Outra melhoria de desempenho é usar valores armazenados em cache ao observar posições via onPlaced().
Pré-busca de texto em segundo plano
A partir da versão 1.9, o Compose adiciona a capacidade de pré-busca de texto em uma linha de execução em segundo plano. Isso permite pré-aquecer caches para ativar um layout de texto mais rápido e é relevante para o desempenho da renderização de apps. Durante o layout, o texto precisa ser transmitido para o framework do Android, onde um cache de palavras é preenchido. Por padrão, isso é executado na linha de execução da interface. Descarregar a pré-busca e preencher o cache de palavras em uma linha de execução em segundo plano pode acelerar o layout, especialmente para textos mais longos. Para pré-buscar em uma linha de execução em segundo plano, transmita um executor personalizado a qualquer elemento combinável que esteja usando BasicText por baixo dos panos transmitindo um LocalBackgroundTextMeasurementExecutor a um CompositionLocalProvider, assim:
val defaultTextMeasurementExecutor = Executors.newSingleThreadExecutor()
CompositionLocalProvider(
LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor
) {
BasicText("Some text that should be measured on a background thread!")
}Dependendo do texto, isso pode melhorar a performance da renderização. Para garantir que ele melhore o desempenho de renderização do seu app, faça um comparativo e compare os resultados.
Considerações sobre o desempenho do trabalho em segundo plano
O trabalho em segundo plano é uma parte essencial de muitos apps. Talvez você esteja usando bibliotecas como WorkManager ou JobScheduler para realizar tarefas como:
- Fazer upload periódico de eventos analíticos
- Sincronizar dados entre um serviço de back-end e um banco de dados
- Processamento de mídia (ou seja, redimensionamento ou compactação de imagens)
Um dos principais desafios ao executar essas tarefas é equilibrar o desempenho e a eficiência energética. O WorkManager permite alcançar esse equilíbrio. Ele foi projetado para ser eficiente em termos de energia e permitir que o trabalho seja adiado para uma janela de execução ideal influenciada por vários fatores, incluindo restrições especificadas por você ou impostas pelo sistema.
No entanto, o WorkManager não é uma solução única para todos os casos. O Android também tem várias APIs otimizadas para energia, projetadas especificamente com algumas jornadas comuns do usuário principal (CUJs, na sigla em inglês) em mente.
Consulte a página de destino do trabalho em segundo plano para ver uma lista de alguns deles, incluindo a atualização de um widget e a obtenção de localização em segundo plano.
Ferramentas de depuração local para trabalho em segundo plano: cenários comuns
Para depurar o trabalho em segundo plano e entender por que uma tarefa pode ter sido atrasada ou falhado, você precisa saber como o sistema programou suas tarefas.
Para ajudar nisso, o WorkManager tem várias ferramentas relacionadas para ajudar você a depurar localmente e otimizar o desempenho. Algumas delas também funcionam com o JobScheduler. Confira alguns cenários comuns que você pode encontrar ao usar o WorkManager e uma explicação das ferramentas que podem ser usadas para depurar esses cenários.
Depurar por que o trabalho programado não está sendo executado
O atraso ou a não execução do trabalho programado pode ser devido a vários fatores, incluindo restrições especificadas que não foram atendidas ou que foram impostas pelo sistema.
A primeira etapa para investigar por que o trabalho programado não está sendo executado é confirmar se ele foi programado corretamente. Depois de confirmar o status do agendamento, determine se há restrições ou pré-condições não atendidas que impedem a execução do trabalho.
Há várias ferramentas para depurar esse cenário.
Inspetor de tarefas em segundo plano
O Inspetor de tarefas em segundo plano é uma ferramenta eficiente integrada diretamente ao Android Studio. Ele fornece uma representação visual de todas as tarefas do WorkManager e os estados associados (em execução, enfileirada, falha, concluída).
Para depurar por que o trabalho programado não está sendo executado com o Inspetor de tarefas em segundo plano, consulte os status de trabalho listados. O status "Enqueued" indica que seu trabalho foi programado, mas ainda está aguardando execução.
Benefícios:além de oferecer uma maneira fácil de ver todas as tarefas, essa ferramenta é especialmente útil se você tiver trabalho encadeado. O Inspetor de tarefas em segundo plano oferece uma visualização em gráfico que pode mostrar se a falha de uma tarefa anterior afetou a execução da tarefa seguinte.
Visualização em lista do Inspetor de tarefas em segundo plano
Visualização de gráfico do Inspetor de tarefas em segundo plano
adb shell dumpsys jobscheduler
Esse comando retorna uma lista de todos os jobs ativos do JobScheduler (que inclui Workers do WorkManager) com restrições especificadas e impostas pelo sistema. Ele também retorna o histórico de jobs.
Use essa opção se quiser uma maneira diferente de ver seu trabalho programado e as restrições associadas. Para versões do WorkManager anteriores à 2.10.0, adb shell dumpsys jobscheduler vai retornar uma lista de Workers com este nome:
[package name]/androidx.work.impl.background.systemjob.SystemJobService
Se o app tiver vários workers, a atualização para o WorkManager 2.10.0 vai permitir que você veja os nomes deles e os diferencie com facilidade:
#WorkerName#@[package name]/androidx.work.impl.background.systemjob.SystemJobService
Benefícios : esse comando é útil para entender se houve restrições impostas pelo sistema , que não podem ser determinadas com o inspetor de tarefas em segundo plano. Por exemplo, isso vai retornar o bucket de espera do app, que pode afetar a janela em que o trabalho programado é concluído.
Ativar a geração de registros de depuração
É possível ativar o registro personalizado para ver registros detalhados do WorkManager, que terão WM— anexado.
Benefícios:isso permite que você tenha visibilidade de quando o trabalho é programado, as restrições são atendidas e os eventos do ciclo de vida. Além disso, é possível consultar esses registros durante o desenvolvimento do app.
WorkInfo.StopReason
Se você notar um desempenho imprevisível com um worker específico, poderá observar programaticamente o motivo da interrupção na tentativa de execução anterior com WorkInfo.getStopReason.
É recomendável configurar o app para observar WorkInfo usando getWorkInfoByIdFlow e identificar se o trabalho está sendo afetado por restrições em segundo plano, restrições, tempos limite frequentes ou até mesmo interrompido pelo usuário.
Benefícios:você pode usar WorkInfo.StopReason para coletar dados de campo sobre a performance dos seus trabalhadores.
Depuração da duração longa de wake lock atribuída ao WorkManager sinalizada pelo Android vitals
O Android vitals tem uma métrica de wake locks parciais em excesso, que destaca os wake locks que contribuem para o consumo elevado da bateria. Talvez você se surpreenda ao saber que o WorkManager adquire bloqueios de despertar para executar tarefas e, se esses bloqueios excederem o limite definido pelo Google Play, isso poderá afetar a visibilidade do seu app. Como depurar por que há tanta duração de wake lock atribuída ao seu trabalho? Você pode usar as seguintes ferramentas.
Painel do Android vitals
Primeiro, confirme no painel do Android vitals sobre wake locks excessivos que a longa duração do wake lock é do WorkManager e não de um alarme ou outro wake lock. Use a documentação Identificar bloqueios de despertar criados por outras APIs para entender quais bloqueios de despertar são mantidos devido ao WorkManager.
Perfetto
O Perfetto é uma ferramenta para analisar rastreamentos do sistema. Ao usar para depurar o WorkManager especificamente, você pode conferir a seção "Estado do dispositivo" para saber quando o trabalho começou, quanto tempo ele foi executado e como ele contribui para o consumo de energia.
Em "Estado do dispositivo: jobs", é possível conferir todos os workers que foram executados e os bloqueios de despertar associados.
Seção "Estado do dispositivo" no Perfetto, mostrando a execução de CleanupWorker e BlurWorker.
Recursos
Consulte a página de depuração do WorkManager para ter uma visão geral dos métodos de depuração disponíveis para outros cenários que você pode encontrar.
Para testar alguns desses métodos na prática e saber mais sobre a depuração da WorkManager, confira o codelab WorkManager avançado e testes.
Próximas etapas
Hoje, fomos além da redução de código e exploramos como o Android Runtime e o Jetpack Compose renderizam seu app. Seja pré-compilando caminhos críticos com perfis de referência ou suavizando estados de rolagem com os novos recursos do Compose 1.9 e 1.10, essas ferramentas se concentram na sensação do seu app. Além disso, analisamos as práticas recomendadas para depurar o trabalho em segundo plano.
Perguntar ao Android
Na sexta-feira, vamos fazer um AMA ao vivo sobre performance. Faça suas perguntas agora usando #AskAndroid e receba respostas dos especialistas.
O desafio
Na segunda-feira, pedimos que você ativasse o R8. Hoje, pedimos que você gere um perfil de referência para seu app.
Com o Android Studio Otter, o assistente de módulo do gerador de perfis de referência facilita ainda mais esse processo. Escolha a jornada ideal do usuário, mesmo que seja apenas a inicialização e o login do app, e gere um perfil.
Depois disso, execute uma Macrobenchmark para comparar CompilationMode.None e CompilationMode.Partial.
Compartilhe suas melhorias no tempo de inicialização nas redes sociais usando a hashtag #optimizationEnabled.
Assista amanhã
Você reduziu o app com o R8 e otimizou o tempo de execução com a otimização guiada por perfil. Mas como provar esses benefícios para as partes interessadas? E como você detecta regressões antes que elas cheguem à produção?
Participe amanhã do Dia 4: Guia de nivelamento de performance, em que vamos mostrar exatamente como medir seu sucesso, desde dados de campo no Play Vitals até rastreamento local detalhado com o Perfetto.
Continuar lendo
-
Tutoriais
Ao trabalhar em novos recursos, o desempenho do app geralmente fica em segundo plano. No entanto, embora nem sempre seja a prioridade dos desenvolvedores, os usuários podem ver exatamente onde o desempenho do app fica aquém.
Ben Weiss • 3 min de leitura
-
Tutoriais
A fiscalização da qualidade técnica da bateria chegou: como otimizar casos de uso comuns de WakeLock
Sabendo que o consumo elevado da bateria é o mais lembrado para os usuários do Android, o Google tem tomado medidas significativas para ajudar os desenvolvedores a criar apps mais eficientes em termos de energia.
Alice Yuan • Leitura de 8 minutos
-
Tutoriais
Queremos mostrar exemplos de recursos com tecnologia de IA usando modelos no dispositivo e na nuvem para inspirar você a criar experiências incríveis para seus usuários.
Thomas Ezan, Ivy Knight • Leitura de 2 minutos
Fique por dentro
Receba os insights mais recentes sobre desenvolvimento Android na sua caixa de entrada semanalmente.