Puedes ejecutar comparativas en integración continua (CI) para hacer un seguimiento del rendimiento a lo largo del tiempo y reconocer regresiones (o mejoras) de rendimiento antes de que se publique tu app. En esta página, se proporciona información básica sobre las comparativas en CI.
Antes de comenzar a realizar comparativas en CI, considera cómo difiere la captura y evaluación de los resultados de las pruebas regulares.
Resultados aproximados
Aunque las comparativas son pruebas instrumentadas, los resultados no son solo aprobatorios o reprobatorios. Las comparativas proporcionan mediciones de tiempo para el dispositivo determinado en el que se ejecutan. Graficar los resultados a lo largo del tiempo te permite supervisar los cambios y observar el ruido en el sistema de medición.
Usa dispositivos reales
Ejecuta comparativas en dispositivos Android físicos. Si bien pueden ejecutarse en emuladores, no es recomendable en absoluto, ya que no representarán una experiencia del usuario realista y proporcionarán números vinculados a las capacidades del hardware y el SO del host. Considera usar dispositivos reales o un servicio que te permita ejecutar pruebas en ellos, como Firebase Test Lab.
Ejecuta las comparativas
Ejecutar las comparativas como parte de la canalización de CI puede ser diferente a ejecutarlas de forma local desde Android Studio. De forma local, normalmente se ejecutan las pruebas de integración de Android con una tarea connectedCheck
de Gradle. Esta tarea compila automáticamente tu APK y el APK de prueba, y ejecuta las pruebas en los dispositivos conectados al servidor de CI. Cuando se ejecuta en CI, por lo general, este flujo debe dividirse en fases separadas.
Compilación
Para la Biblioteca de microcomparativas, ejecuta la tarea de Gradle assemble[VariantName]AndroidTest
, que crea tu APK de prueba que contiene el código de la aplicación y el código que probaste.
De manera alternativa, la Biblioteca de macrocomparativas requiere que compiles tu APK de destino y el APK de prueba por separado. Por lo tanto, ejecuta las tareas de Gradle :app:assemble[VariantName]
y :macrobenchmark:assemble[VariantName]
.
Instalación y ejecución
Generalmente, estos pasos se realizan sin necesidad de ejecutar tareas de Gradle. Ten en cuenta que se pueden abstraer dependiendo de si usas un servicio que te permite ejecutar pruebas en dispositivos reales.
Para la instalación, usa el comando adb install
y especifica el APK de prueba o el APK de destino.
Ejecuta el comando de instrumento adb shell am
para ejecutar todas las comparativas.
adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
Cuando utilices la biblioteca de Macrobenchmark, usa el objeto androidx.test.runner.AndroidJUnitRunner
normal como ejecutor de instrumentación.
Puedes pasar los mismos argumentos de instrumentación que en la configuración de Gradle con el argumento -e
. Si quieres conocer todas las opciones de argumentos de instrumentación, consulta Argumentos de instrumentación de microcomparativas o Cómo agregar argumentos de instrumentación para Macrobenchmark.
Por ejemplo, puedes configurar el argumento dryRunMode
para ejecutar microcomparativas como parte de tu proceso de verificación de solicitud de extracción. Con esta marca habilitada, las microcomparativas se ejecutan solo en un bucle único, lo que permite verificar que se ejecuten de forma correcta, pero que no tarden demasiado en ejecutarse.
adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
Si quieres obtener más información para ejecutar pruebas de instrumentación desde la línea de comandos, consulta Cómo ejecutar pruebas con ADB.
Bloquea relojes
El complemento de Gradle para microcomparativas proporciona el comando ./gradlew lockClocks
para bloquear los relojes de la CPU de un dispositivo con permisos de administrador. Esto es útil para garantizar la estabilidad cuando tienes acceso a dispositivos con permisos de administrador, como compilaciones "userdebug". Puedes replicar esta acción con la secuencia de comandos de shell lockClocks.sh
, que está disponible en la fuente de la biblioteca.
Puedes ejecutar la secuencia de comandos directamente desde un host de Linux o Mac, o bien enviarla al dispositivo con algunos 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
Si ejecutas la secuencia de comandos de shell directamente en un host, este envía los comandos a un dispositivo conectado.
Para obtener más información sobre por qué es útil bloquear los relojes de la CPU, consulta cómo obtener comparativas coherentes.
Recopila los resultados
Las bibliotecas de comparativas generan mediciones en JSON, junto con registros de la generación de perfiles, en un directorio en el dispositivo Android después de cada ejecución de comparativas. La biblioteca de Macrobenchmark genera varios archivos de registro de perfetto: uno por iteración medida de cada bucle MacrobenchmarkRule.measureRepeated
. Sin embargo, la de Microbenchmark crea solo un archivo de registro para todas las iteraciones de cada BenchmarkRule.measureRepeated
. Los archivos de registro de generación de perfiles también se envían a este mismo directorio.
Guarda y ubica los archivos
Si ejecutas comparativas con Gradle, estos archivos se copian automáticamente en el directorio de salidas de tu computadora host en build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/
.
Si ejecutas de manera directa con el comando adb
, debes extraer los archivos de forma manual. De forma predeterminada, los informes se guardan en el dispositivo dentro del directorio de contenido multimedia del almacenamiento externo de la app probada. Para mayor comodidad, la biblioteca muestra la ruta de acceso del archivo en Logcat. Ten en cuenta que la carpeta de salida puede ser diferente según la versión de Android en la que se ejecuten las comparativas.
Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
También puedes configurar la ubicación en la que se guardan los informes de comparativas en el dispositivo. Para ello, usa el argumento de instrumentación additionalTestOutputDir
. La app debe poder escribir en esta carpeta.
adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
En Android 10 (nivel de API 29) y versiones posteriores, las pruebas de tu app se ejecutan en una zona de pruebas de almacenamiento de forma predeterminada, lo que evita que la app acceda a archivos fuera del directorio específico de la app. Para poder guardar en un directorio global, como /sdcard/Download
, pasa el siguiente argumento de instrumentación:
-e no-isolated-storage true
También debes permitir de manera explícita las opciones de almacenamiento heredado en el manifiesto de tus comparativas:
<application android:requestLegacyExternalStorage="true" ... >
Consulta Cómo inhabilitar temporalmente el almacenamiento específico para obtener más información.
Recupera los archivos
Para obtener los archivos generados del dispositivo, usa el comando adb pull
, que extrae el archivo especificado en el directorio actual de tu host:
adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
Para recuperar todos los benchmarkData
de una carpeta especificada, verifica el siguiente fragmento:
# 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
Los archivos de registro (.trace
o .perfetto-trace
) se guardan en la misma carpeta que benchmarkData.json
, por lo que puedes recopilarlos de la misma manera.
Ejemplo de datos de comparativas
Las bibliotecas de comparativas generan archivos JSON que contienen información sobre el dispositivo en el que se ejecutaron las comparativas y las comparativas reales que ejecutó. El siguiente fragmento representa el archivo JSON que se genera:
{
"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
}
]
}
Recursos adicionales
- Si quieres obtener orientación para detectar regresiones de rendimiento, consulta Fighting Regressions with Benchmarks in CI.
- Para ver cómo configurar acciones de GitHub con Firebase Test Lab, consulta Setting up Jetpack Macrobenchmarks for CI
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Prácticas recomendadas para el rendimiento de SQLite
- Cómo crear y medir perfiles de Baseline sin macrocomparativas
- Bloqueos de activación sostenidos parciales