Você pode fazer comparações em integração contínua (CI) para acompanhar o desempenho ao longo do tempo e reconhecer regressões de desempenho (ou melhorias) antes mesmo do lançamento do app. Nesta página, você encontra informações básicas sobre comparações em CI.
Antes de começar a usar a comparação em CI, considere como a captura e avaliação dos resultados é diferente dos testes regulares.
Resultados fuzzy
Embora as comparações sejam testes de instrumentação, os resultados não são apenas uma aprovação ou reprovação. As comparações fornecem medições de tempo para o dispositivo em que são executadas. Com os gráficos de resultados ao longo do tempo, você pode monitorar as mudanças e observar o ruído no sistema de medidas.
Usar dispositivos reais
Faça as comparações em dispositivos físicos Android. Embora seja possível, não é recomendado fazer isso em emuladores, já que eles não representam uma experiência realista do usuário e fornecem números vinculados aos recursos de SO e hardware do host. Use dispositivos reais ou um serviço que permita executar testes em dispositivos reais, como o Firebase Test Lab.
Executar as comparações
A execução das comparações como parte do pipeline de CI pode ser diferente da execução local
no Android Studio. Normalmente, os testes de integração do Android
são executados com uma tarefa connectedCheck
do Gradle. Essa tarefa cria
automaticamente os APKs de destino e teste e executa os testes nos dispositivos conectados
ao servidor de CI. Com a execução em CI, esse fluxo geralmente precisa ser dividido em
etapas separadas.
Criar
Para a biblioteca Microbenchmark, execute a tarefa assemble[VariantName]AndroidTest
do
Gradle, que cria o APK de teste que contém
o código do aplicativo e o código testado.
Como alternativa, a biblioteca Macrobenchmark pede que você crie o APK de destino e
o APK de teste separadamente. Portanto, execute as tarefas
:app:assemble[VariantName]
e :macrobenchmark:assemble[VariantName]
do Gradle.
Instalar e executar
Geralmente, essas etapas são realizadas sem a necessidade de tarefas do Gradle, que podem ser abstraídas se você usa um serviço que permite executar os testes em dispositivos reais.
Para a instalação, use o comando adb install
e especifique o APK de teste
ou o APK de destino.
Execute o comando de instrumento adb shell am
para gerar todas as comparações:
adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
Ao usar a biblioteca Macrobenchmark, use o androidx.test.runner.AndroidJUnitRunner
normal como executor de instrumentação.
Você pode transmitir os mesmos argumentos de instrumentação usados na configuração do Gradle
com o argumento -e
. Para conferir todas as opções de argumentos, consulte
Argumentos de instrumentação de Microbenchmark ou
Adicionar argumentos de instrumentação para a Macrobenchmark.
Por exemplo, você pode definir o argumento dryRunMode
para executar microcomparações como
parte do processo de verificação de solicitação de envio. Com essa flag ativada,
as microcomparações são geradas apenas em um único loop, verificando se estão sendo executadas
corretamente, mas sem levar muito tempo no processo.
adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
Para saber mais sobre como executar testes de instrumentação na linha de comando, consulte Executar testes com o adb.
Bloquear relógios
O plug-in do Gradle de Microbenchmark fornece o comando ./gradlew lockClocks
para
bloquear os clocks da CPU de um dispositivo com acesso root. Isso é útil para garantir que haja estabilidade
em dispositivos com acesso root, como as versões "userdebug". É possível
replicar isso com o script de shell lockClocks.sh
, disponível na
origem da biblioteca.
É possível executar o script diretamente de um host Linux ou Mac ou enviá-lo para o dispositivo com alguns comandos adb:
adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh adb shell /data/local/tmp/lockClocks.sh adb shell rm /data/local/tmp/lockClocks.sh
Se você executar o script de shell diretamente em um host, ele vai enviar esses comandos a um dispositivo conectado.
Saiba mais sobre como receber comparações consistentes para entender por que é útil bloquear os clocks da CPU.
Coletar os resultados
As bibliotecas de comparação geram medições em
JSON, bem como rastros de caracterização de perfil para um diretório no
dispositivo Android após cada comparação. A biblioteca Macrobenchmark gera
vários arquivos de rastreamento do perfetto, um por iteração medida de cada
loop MacrobenchmarkRule.measureRepeated
. No entanto, a Microbenchmark cria
apenas um arquivo de rastreamento para todas as iterações de cada
BenchmarkRule.measureRepeated
. A caracterização de perfil com arquivos de rastreamento também é enviada para
o mesmo diretório.
Salvar e localizar os arquivos
Se você executar as comparações com o Gradle, esses arquivos serão copiados automaticamente para
o diretório de saídas do computador host em
build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/
.
Se a comparação estiver em execução direta com o comando adb
, você vai precisar copiar os arquivos
manualmente. Por padrão, os relatórios são armazenados no dispositivo, no diretório de mídia
do armazenamento externo do app testado. Por conveniência, a biblioteca mostra o caminho
do arquivo no Logcat. A pasta de saída pode ser diferente, dependendo
da versão do Android em que as comparações estão sendo executadas.
Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
Também é possível configurar o local em que os relatórios de comparação serão armazenados no
dispositivo usando o argumento de instrumentação additionalTestOutputDir
. O
app precisa ter permissões de gravação nessa pasta.
adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
No Android 10 (nível 29 da API) e versões mais recentes, por padrão, os testes do app são executados em um sandbox
de armazenamento, evitando que ele acesse arquivos fora do
diretório específico. Para salvar em um diretório global, como
/sdcard/Download
, transmita o seguinte argumento de
instrumentação:
-e no-isolated-storage true
Também é necessário permitir explicitamente as opções de armazenamento legadas no manifesto da comparação:
<application android:requestLegacyExternalStorage="true" ... >
Para saber mais informações, consulte Desativar temporariamente o armazenamento com escopo.
Recuperar os arquivos
Para recuperar os arquivos gerados no dispositivo, use o comando
adb pull
, que extrai o arquivo especificado no diretório atual do host:
adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
Para recuperar todo o benchmarkData
de uma pasta especificada, confira o
seguinte snippet:
# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull
Os arquivos de rastreamento (.trace
ou .perfetto-trace
) são armazenados na mesma
pasta que o benchmarkData.json
. Assim, você pode encontrá-los da mesma maneira.
Exemplo de dados de comparação
As bibliotecas de comparação geram arquivos JSON com informações sobre o dispositivo em que o processo estava sendo executado e sobre as comparações executadas. O snippet a seguir representa o arquivo JSON gerado:
{
"context": {
"build": {
"brand": "google",
"device": "blueline",
"fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
"model": "Pixel 3",
"version": {
"sdk": 31
}
},
"cpuCoreCount": 8,
"cpuLocked": false,
"cpuMaxFreqHz": 2803200000,
"memTotalBytes": 3753299968,
"sustainedPerformanceModeEnabled": false
},
"benchmarks": [
{
"name": "startup",
"params": {},
"className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
"totalRunTimeNs": 4975598256,
"metrics": {
"timeToInitialDisplayMs": {
"minimum": 347.881076,
"maximum": 347.881076,
"median": 347.881076,
"runs": [
347.881076
]
}
},
"sampledMetrics": {},
"warmupIterations": 0,
"repeatIterations": 3,
"thermalThrottleSleepSeconds": 0
}
]
}
Outros recursos
- Para entender melhor a detecção de regressões de desempenho, consulte Como combater regressões com comparações em CI.
- Para aprender a configurar o GitHub Actions com o Firebase Test Lab, consulte Como configurar a biblioteca Jetpack Macrobenchmarks para CI.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Práticas recomendadas para a performance do SQLite
- Criar e medir perfis de referência sem a Macrobenchmark
- Wake locks parciais travados