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 a diferença entre captura e avaliação dos resultados e testes regulares.
Resultados complexos
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
As comparações devem ser executadas 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
seriam executados com uma tarefa connectedCheck
do Gradle. Essa tarefa cria
automaticamente os APKs de destino e de teste e executa os testes nos dispositivos
conectados no momento. Com a execução em CI, esse fluxo geralmente precisa ser dividido em fases
separadas.
Build
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 ver todas as opções de argumentos, consulte as
páginas Microbenchmark ou 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, permitindo verificar 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
Consulte Como executar testes com o adb para ver mais informações sobre a execução de testes de instrumentação na linha de comando.
Bloquear relógios
O plug-in do Gradle de Microbenchmark fornece o comando ./gradlew lockClocks
para
bloquear os relógios 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 enviará esses comandos para um dispositivo conectado.
Para saber por que é útil bloquear os relógios da CPU, veja como receber comparações consistentes.
Coletar os resultados
As bibliotecas de comparação geram medições em
JSON, além de 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 vão ser 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 copiá-los
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 imprime 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 vão ser armazenados no
dispositivo usando o argumento de instrumentação additionalTestOutputDir
. O aplicativo precisa ter permissões de gravação nesta 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 ver mais informações, consulte Desativar temporariamente o armazenamento com escopo.
Recuperar os arquivos
Para encontrar 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, veja 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 ver orientações sobre a detecção de regressões de desempenho, consulte Como combater regressões com comparações em CI.
- Para ver como configurar o GitHub Actions com o Firebase Test Lab, consulte Como configurar a biblioteca Jetpack Macrobenchmarks para CI.