Puedes comenzar a usar rápidamente la biblioteca de Microbenchmark si agregas cambios al código de la aplicación. Para lograr una configuración de proyecto adecuada, sigue lo que se indica en la sección Configuración completa, que requiere cambios más complicados en la base de código.
Guía de inicio rápido
En esta sección, se proporciona una guía rápida a fin de probar las comparativas y ejecutar mediciones únicas sin necesidad de mover código a los módulos. Para obtener resultados de rendimiento exactos, estos pasos implican inhabilitar la depuración en tu aplicación, por lo que debes conservar esta configuración en una copia de trabajo local sin confirmar los cambios en el sistema fuente de control.
A fin de generar rápidamente comparativas únicas, completa los siguientes pasos:
Agrega la biblioteca al archivo
build.gradle
del módulo:project_root/module_dir/build.gradle
Groovy
dependencies { androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.1.1' }
Kotlin
dependencies { androidTestImplementation("androidx.benchmark:benchmark-junit4:1.1.1") }
Si deseas inhabilitar la depuración en el manifiesto de prueba, actualiza el elemento
<application>
a fin de forzar la inhabilitación de la depuración de manera temporal:project_root/module_dir/src/androidTest/AndroidManifest.xml
<!-- Important: disable debuggable for accurate performance results --> <application android:debuggable="false" tools:ignore="HardcodedDebugMode" tools:replace="android:debuggable"/>
Para agregar tu comparativa, agrega una instancia de la clase
BenchmarkRule
en un archivo de prueba del directorioandroidTest
. Consulta Cómo crear una clase de Microbenchmark para descubrir cómo escribir comparativas.En el siguiente fragmento de código se muestra cómo agregar comparativas a una prueba de JUnit:
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(); } } }
Si deseas ver cómo escribir una comparativa, avanza a la sección Cómo crear una clase de Microbenchmark.
Configuración completa del proyecto
Para configurar la generación de comparativas regulares en lugar de las comparativas únicas, debes aislarlas en su propio módulo. De esta manera, podrás asegurarte de que su configuración, como establecer debuggable
en false
, sea independiente de las pruebas regulares.
Debido a que Microbenchmark ejecuta tu código de forma directa, debes colocar el código que quieras comparar en un módulo de Gradle separado y establecer la dependencia en ese módulo, como se muestra en la siguiente figura.
Para agregar un nuevo módulo de Gradle, puedes usar el asistente de módulos en Android Studio. El asistente crea un módulo configurado previamente para la generación de comparativas, con un directorio de comparativas y el valor debuggable
configurado como false
.
Bumblebee (o una versión más reciente)
- Haz clic con el botón derecho en tu proyecto o módulo desde el panel Project en Android Studio y haz clic en New > Module.
- Selecciona Benchmark en el panel Templates.
- Selecciona Microbenchmark como tipo de módulo de comparativas.
- Como nombre de módulo, escribe "microbenchmark".
- Haz clic en Finish.
Arctic Fox
- Haz clic con el botón derecho en tu proyecto o módulo desde el panel Project en Android Studio y haz clic en New > Module.
- Selecciona Benchmark en el panel Templates.
- Como nombre de módulo, escribe "microbenchmark".
- Haz clic en Finish.
Después de crear el módulo, cambia su archivo build.gradle
y agrega testImplementation
al módulo que contiene el código para crear comparativas:
Groovy
dependencies { // Note, that the module name may be different androidTestImplementation project(':benchmarkable') }
Kotlin
dependencies { // Note, that the module name may be different androidTestImplementation(project(":benchmarkable")) }
Cómo crear una clase de Microbenchmark
Las comparativas son pruebas de instrumentación estándar. Para crear comparativas, usa la clase BenchmarkRule
que proporciona la biblioteca. Si deseas comparar actividades, usa ActivityTestRule
o ActivityScenarioRule
. Usa @UiThreadTest
para comparar código de IU.
En el siguiente código se muestran comparativas de ejemplo:
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(); } } }
Cómo inhabilitar la sincronización
Puedes inhabilitar la sincronización para secciones de código que no quieras medir con el bloque runWithTimingDisabled{}
. Por lo general, estas secciones representan algún código que necesitas ejecutar en cada iteración de la comparativa.
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() { // using random with the same seed, so that it generates the same data every run Random random = new Random(0); // create the array once and just 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)); }
Intenta minimizar la cantidad de trabajo realizado dentro del bloque measureRepeated
, así como dentro de runWithTimingDisabled
. El bloque measureRepeated
se ejecuta varias veces y puede afectar el tiempo general necesario para ejecutar la comparativa.
Si necesitas verificar algunos resultados de una comparativa, puedes confirmar el último resultado en lugar de hacerlo en cada iteración de la comparativa.
Cómo ejecutar las comparativas
En Android Studio, ejecuta tus comparativas como lo harías con cualquier @Test
mediante la acción del margen junto a tu clase o método de prueba, como se muestra en la siguiente imagen.
Como alternativa, desde la línea de comandos, ejecuta connectedCheck
para ejecutar todas las pruebas del módulo de Gradle especificado:
./gradlew benchmark:connectedCheck
También puedes ejecutar una sola prueba:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
Resultados de comparativas
Después de ejecutar Microbenchmark con éxito, se muestran las métricas directamente en Android Studio, así como un informe de comparativas completo con información adicional del dispositivo y métricas disponibles en formato JSON.
Los informes de JSON y cualquier seguimiento de perfiles también se copian automáticamente del dispositivo al host. Estos están escritos en la máquina host en la siguiente string:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
De manera predeterminada, el informe de JSON está escrito en el dispositivo en la carpeta de descargas compartida externa del APK de prueba que, por lo general, se encuentra en /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json
.
Errores de configuración
La biblioteca detecta las siguientes condiciones a fin de garantizar que tu proyecto y entorno estén configurados para un rendimiento acorde a un lanzamiento:
- Debuggable está configurado en
false
. - Se está usando un dispositivo físico (no se admiten emuladores).
- Los relojes están bloqueados si el dispositivo tiene permisos de administrador.
- El nivel de batería en el dispositivo es suficiente (es de al menos 25%).
Si alguna de las verificaciones anteriores falla, las comparativas informan un error para desalentar las mediciones imprecisas.
Para hacer que algunos tipos de error específicos pasen como advertencias y evitar que detengan las comparativas, pasa el tipo de error en una lista separada por comas al argumento de instrumentación androidx.benchmark.suppressErrors
.
Esto se puede configurar desde tu secuencia de comandos de Gradle como se muestra a continuación:
Groovy
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Ten en cuenta que suprimir errores permite que las comparativas se ejecuten en un estado de configuración incorrecta, pero se le cambiará intencionalmente el nombre del resultado de las comparativas anteponiendo nombres de pruebas con el error. Por ejemplo, ejecutar una comparativa depurable con la supresión del fragmento anterior antepone DEBUGGABLE_
a los nombres de prueba.