Para aprender a usar a biblioteca Microbenchmark adicionando mudanças no código do aplicativo, consulte a seção Guia de início rápido. Para saber como concluir uma configuração completa com mudanças mais complicadas na base de código, consulte a seção Configuração completa do projeto.
Guia de início rápido
Esta seção mostra como testar as comparações e executar medições únicas sem ter que mover o código para os módulos. Para que os resultados de desempenho sejam precisos, estas etapas envolvem desativar a depuração no app. Portanto, mantenha uma cópia local de trabalho sem confirmar as mudanças no sistema de controle de origem.
Para realizar uma comparação única, siga estas etapas:
Adicione a biblioteca ao arquivo
build.gradle
oubuild.gradle.kts
do módulo:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
Groovy
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
Usar uma dependência
implementation
em vez deandroidTestImplementation
. Se você usarandroidTestImplementation
, as comparações não vão executada porque o manifesto da biblioteca não está mesclado ao app. manifesto do aplicativo.Atualize o tipo de build
debug
para que ele não seja depurável:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Groovy
android { ... buildTypes { debug { debuggable false } } }
Mude
testInstrumentationRunner
paraAndroidBenchmarkRunner
:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Groovy
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Inclua uma instância de
BenchmarkRule
em um arquivo de teste no diretórioandroidTest
para adicionar a comparação. Para saber mais sobre como criar comparações, consulte Criar uma classe de Microbenchmark.O snippet de código a seguir mostra como adicionar uma comparação a um teste instrumentado:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { BenchmarkRuleKt.measureRepeated( (Function1<BenchmarkRule.Scope, Unit>) scope -> doSomeWork() ); } } }
Para aprender a criar uma comparação, consulte Criar uma classe de Microbenchmark.
Configuração completa do projeto
Para configurar comparações frequentes, em vez de uma única,
isole as comparações em módulos. Isso garante que a configuração,
como definir debuggable
como false
, seja diferente dos testes normais.
Como a Microbenchmark executa o código diretamente, coloque o código que você quer comparar em um módulo separado do Gradle e defina a dependência nele, como mostrado na figura 1.
Use o assistente do Android Studio para adicionar um novo módulo do Gradle. O
assistente cria um módulo pré-configurado, com um
diretório de comparação e debuggable
definido como false
.
Clique com o botão direito do mouse no seu projeto ou módulo no painel Project do Android Studio e clique em New > Module.
Selecione a opção Benchmark no painel Templates.
Selecione a Microbenchmark como tipo de módulo de comparações.
Digite "microbenchmark" como o nome do módulo.
Clique em Finish.
Após a criação do módulo, mude o arquivo build.gradle
ou build.gradle.kts
e adicione androidTestImplementation
ao módulo que contém o código que será
comparado:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Groovy
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
Criar uma classe de Microbenchmark
As comparações são testes de instrumentação padrão. Para criar uma comparação, use a
classe BenchmarkRule
oferecida pela biblioteca. Para comparar atividades, use
ActivityScenario
ou ActivityScenarioRule
. Para comparar o código da interface,
use @UiThreadTest
.
O código a seguir apresenta uma amostra de comparação:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { doSomeWork(); } } }
Desativar a medição do tempo de configuração
É possível desativar a medição de tempo para as seções de código que você não quer avaliar usando o
bloco runWithTimingDisabled{}
. Essas seções geralmente representam um código
que você precisa executar em cada iteração da comparação.
Kotlin
// using random with the same seed, so that it generates the same data every run private val random = Random(0) // create the array once and just copy it in benchmarks private val unsorted = IntArray(10_000) { random.nextInt() } @Test fun benchmark_quickSort() { // ... benchmarkRule.measureRepeated { // copy the array with timing disabled to measure only the algorithm itself listToSort = runWithTimingDisabled { unsorted.copyOf() } // sort the array in place and measure how long it takes SortingAlgorithms.quickSort(listToSort) } // assert only once not to add overhead to the benchmarks assertTrue(listToSort.isSorted) }
Java
private final int[] unsorted = new int[10000]; public SampleBenchmark() { // Use random with the same seed, so that it generates the same data every // run. Random random = new Random(0); // Create the array once and copy it in benchmarks. Arrays.setAll(unsorted, (index) -> random.nextInt()); } @Test public void benchmark_quickSort() { final BenchmarkState state = benchmarkRule.getState(); int[] listToSort = new int[0]; while (state.keepRunning()) { // Copy the array with timing disabled to measure only the algorithm // itself. state.pauseTiming(); listToSort = Arrays.copyOf(unsorted, 10000); state.resumeTiming(); // Sort the array in place and measure how long it takes. SortingAlgorithms.quickSort(listToSort); } // Assert only once, not to add overhead to the benchmarks. assertTrue(SortingAlgorithmsKt.isSorted(listToSort)); }
Tente minimizar a quantidade de trabalho feito dentro do bloco measureRepeated
e dentro de runWithTimingDisabled
. O bloco measureRepeated
é executado
várias vezes e pode afetar o tempo total necessário para fazer a comparação. Se for
preciso verificar resultados de uma comparação, declare o último resultado
em vez de fazer todas as iterações.
Executar a comparação
No Android Studio, execute a comparação da mesma forma que faria com qualquer @Test
usando a
ação de gutter ao lado da classe ou do método de teste, conforme mostrado na Figura 3.
Na linha de comando, você também pode executar connectedCheck
para fazer todos os
testes do módulo especificado do Gradle:
./gradlew benchmark:connectedCheck
Ou, para executar um único teste:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
Resultados da comparação
Após a execução de uma comparação da Microbenchmark, as métricas são mostradas diretamente no Android Studio, e um relatório de comparação completo com mais métricas e informações sobre o dispositivo é gerado no formato JSON.
Os relatórios JSON e todos os rastros de criação de perfil também são copiados automaticamente do dispositivo para o host. Eles são gravados na máquina host no seguinte local:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
Por padrão, o relatório JSON é gravado no disco do dispositivo na pasta de mídias
compartilhadas externas do APK de teste, que normalmente fica localizada em
/storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json
.
Erros de configuração
A biblioteca detecta as condições a seguir para garantir que o projeto e o ambiente estejam configurados de modo a apresentar uma performance precisa para a versão:
- O atributo "Debuggable" está definido como
false
. - Um dispositivo físico está sendo usado. Não há suporte a emuladores.
- A frequência do processador está bloqueada, caso o dispositivo tenha acesso root.
- O dispositivo está com um nível de bateria suficiente de pelo menos 25%.
Se alguma das condições anteriores não for respeitada, a comparação vai informar um erro para evitar medições imprecisas.
Para suprimir tipos específicos de erro, como avisos, e impedir que interrompam a
comparação, transmita o tipo de erro em uma lista separada por vírgulas ao argumento
de instrumentação androidx.benchmark.suppressErrors
.
Você pode definir isso no script do Gradle, conforme mostrado no exemplo a seguir:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Groovy
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Também é possível suprimir erros usando a linha de comando:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
A supressão de erros permite que a comparação seja executada em uma configuração incorreta,
e a saída da comparação é renomeada intencionalmente ao adicionar o erro aos
nomes de teste. Por exemplo, executar uma comparação depurável com a
supressão no snippet anterior adiciona DEBUGGABLE_
como prefixo aos nomes dos testes.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Como criar uma comparação da Macrobenchmark
- Criar comparações da Microbenchmark sem o Gradle
- Criar perfis de referência {:#creating-profile-rules}