Cómo crear perfiles de Baseline

Genera perfiles automáticamente para cada versión de la app con la biblioteca de Jetpack Macrobenchmark y BaselineProfileRule. Te recomendamos que uses com.android.tools.build:gradle:8.0.0, que incluye mejoras de compilación con el uso de perfiles de Baseline, o una versión posterior.

Estos son los pasos generales para crear un nuevo perfil de Baseline:

  1. Configura el módulo de perfiles de Baseline.
  2. Define la prueba de JUnit que ayuda a generar los perfiles de Baseline.
  3. Agrega los recorridos críticos del usuario (CUJ) que quieres optimizar.
  4. Genera el perfil de Baseline.

Una vez que generes el perfil Baseline, obtén comparativas usando un dispositivo físico para medir las mejoras de velocidad.

Cómo crear un nuevo perfil de Baseline con AGP 8.2 o versiones posteriores

La forma más fácil de crear un nuevo Perfil de Baseline es usar la plantilla del módulo de Perfil de Baseline, disponible a partir de Android Studio Iguana y el complemento de Android para Gradle (AGP) 8.2.

La plantilla del módulo generador de perfiles de Baseline de Android Studio automatiza la creación de un módulo nuevo para generar y comparar perfiles de Baseline. Ejecutar la plantilla genera la mayor parte de la configuración de compilación típica, la generación de perfiles de Baseline y el código de verificación. La plantilla crea código para generar y comparar perfiles de Baseline, y medir el inicio de la app.

Configura el módulo de perfiles de Baseline

Para ejecutar la plantilla del módulo de perfiles de Baseline, sigue estos pasos:

  1. Selecciona File > New > New Module.
  2. Selecciona la plantilla Baseline Profile Generator en el panel Templates y configúrala:
    Figura 1: Plantilla del módulo generador de Perfiles de Baseline.

    Los campos de la plantilla son los siguientes:

    • Target application: Este campo define para qué app se genera el perfil de Baseline. Cuando solo tienes un módulo de app en tu proyecto, se muestra un solo elemento en esta lista.
    • Module name: Es el nombre que deseas para el módulo de perfiles de Baseline que crearás.
    • Package name: Es el nombre del paquete que deseas para el módulo del perfiles de Baseline.
    • Language: Indica si deseas que el código generado sea Kotlin o Java.
    • Build configuration language: Indica si quieres usar la secuencia de comandos de Kotlin (KTS) o Groovy para tus secuencias de comandos de configuración de compilación.
    • Usa un dispositivo administrado por Gradle: Indica si usas dispositivos administrados por Gradle para probar tu app.
  3. Haz clic en Finish y se creará el módulo nuevo. Si usas el control de código fuente, es posible que se te solicite agregar los archivos de módulo creados recientemente al control de código fuente.

Cómo definir el generador de perfiles de Baseline

El módulo recién creado contiene pruebas para generar y comparar el perfil de Baseline, y probar solo los tiempos de inicio básicos de la app. Te recomendamos que las aumentes para incluir CUJ y flujos de trabajo de inicio avanzados. Asegúrate de que las pruebas relacionadas con el inicio de la app estén en un bloque rule con includeInStartupProfile establecido en true. Por el contrario, para un rendimiento óptimo, asegúrate de que las pruebas que no estén relacionadas con el inicio de la app no estén incluidas en un perfil de inicio. Las optimizaciones de inicio de la app se usan para definir una parte especial de un perfil de Baseline llamada Perfil de inicio.

Para mejorar la capacidad de mantenimiento, abstrae los CUJ fuera del perfil de Baseline generado y genera comparativas del código, de modo que se puedan usar para ambos. Esto significa que los cambios en tus CUJ se usarán de manera coherente.

Genera e instala el perfil de Baseline

La plantilla del módulo de perfiles de Baseline agrega una nueva configuración de ejecución para generar el perfil de Baseline: Si usas variantes de productos, Android Studio crea varias configuraciones de ejecución, de modo que puedas generar perfiles de Baseline independientes para cada variante.

Configuración de ejecución para generar perfiles de Baseline.
Figura 2: Cuando se ejecuta esta configuración, se genera el perfil de Baseline.

Cuando se completa la configuración de ejecución Generate Baseline Profile, se copia el perfil de Baseline generado en src/variant/generated/baselineProfiles/baseline-prof.txt en el módulo para el que se genera el perfil. Las opciones de variante son el tipo de compilación de lanzamiento o una variante de compilación que involucra el tipo de compilación de lanzamiento.

El perfil de Baseline generado se crea originalmente en build/outputs. La variante de la app para la que se crea el perfil determina la ruta completa y si se usa un dispositivo administrado por Gradle o un dispositivo conectado para la generación del perfil. Si utilizas los nombres que usa el código y las configuraciones de compilación que genera la plantilla, el perfil de Baseline se crea en el archivo build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. Es probable que no tengas que interactuar directamente con esta versión del perfil de Baseline generado a menos que lo copies de forma manual a los módulos de destino (no recomendado).

Cómo crear un nuevo perfil de Baseline con AGP 8.1

Si no puedes usar la plantilla del módulo de perfiles de Baseline, usa la del módulo de Macrobenchmark y el complemento de Gradle para perfiles de Baseline para crear un perfil nuevo. Te recomendamos que uses estas herramientas a partir de Android Studio Giraffe y AGP 8.1.

Estos son los pasos para crear un nuevo perfil de Baseline usando la plantilla de módulos de Macrobenchmark y el complemento de Gradle para perfiles de Baseline:

  1. Configura un módulo de Macrobenchmark en tu proyecto de Gradle.
  2. Define una clase nueva llamada BaselineProfileGenerator:
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }
    

    El generador puede contener interacciones con tu app más allá del inicio de la app. Esto te permite optimizar el rendimiento del tiempo de ejecución de tu app, por ejemplo, desplazarse por listas, ejecutar animaciones y navegar dentro de una Activity. Consulta otros ejemplos de pruebas que usan @BaselineProfileRule para mejorar los recorridos críticos del usuario.

  3. Agrega el complemento de Gradle para Perfiles de Baseline (libs.plugins.androidx.baselineprofile). El complemento facilita la generación de Perfiles de Baseline y su mantenimiento en el futuro.

  4. Para generar el perfil de Baseline, ejecuta las tareas de Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile en la terminal.

    Ejecuta el generador como una prueba de instrumentación en un dispositivo físico con permisos de administrador, en un emulador o en un dispositivo administrado por Gradle. Si usas uno de estos dispositivos, establece aosp como la systemImageSource, ya que necesitas acceso con permisos de administrador para el generador de perfiles de Baseline.

    Al final de la tarea de generación, el perfil de Baseline se copia en app/src/variant/generated/baselineProfiles.

Cómo crear un nuevo perfil de Baseline sin plantillas

Te recomendamos que crees un perfil de Baseline usando la plantilla de módulos de perfiles de Baseline de Android Studio (opción preferida) o la plantilla de Macrobenchmark, pero también puedes usar el complemento de Gradle para perfiles de Baseline por sí mismo. Si deseas leer más sobre el complemento de Gradle para perfiles de Baseline, consulta Cómo configurar la generación de perfiles de Baseline.

Estos son los pasos para crear un Perfil de Baseline usando directamente el complemento de Gradle para Perfiles de Baseline:

  1. Crea un módulo com.android.test nuevo, por ejemplo, :baseline-profile.
  2. Configura el archivo build.gradle.kts para :baseline-profile:

    1. Aplica el complemento androidx.baselineprofile.
    2. Asegúrate de que targetProjectPath apunte al módulo :app.
    3. De forma opcional, agrega un dispositivo administrado por Gradle (GMD). En el siguiente ejemplo, es pixel6Api31. Si no se especifica, el complemento usa un dispositivo conectado, ya sea emulado o físico.
    4. Aplica la configuración que desees, como se muestra en el siguiente ejemplo.

    Kotlin

    plugins {
        id("com.android.test")
        id("androidx.baselineprofile")
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath = ":app"
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device = "Pixel 6"
                apiLevel = 31
                systemImageSource = "aosp"
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices += "pixel6Api31"
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices = false
    }
    

    Groovy

    plugins {
        id 'com.android.test'
        id 'androidx.baselineprofile'
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath ':app'
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device 'Pixel 6'
                apiLevel 31
                systemImageSource 'aosp'
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices ['pixel6Api31']
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices false
    }
    
  3. Crea una prueba de Perfil de Baseline en el módulo de prueba de :baseline-profile. El siguiente ejemplo es una prueba que inicia la app y espera el estado inactivo.

    Kotlin

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }
    

    Java

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
    
  4. Actualiza el archivo build.gradle.kts en el módulo de la app, por ejemplo, :app.

    1. Aplica el complemento androidx.baselineprofile.
    2. Agrega una dependencia baselineProfile al módulo :baseline-profile.

    Kotlin

    plugins {
        id("com.android.application")
        id("androidx.baselineprofile")
    }
    
    android {
        // There are no changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile(project(":baseline-profile"))
    }
    

    Groovy

    plugins {
        id 'com.android.application'
        id 'androidx.baselineprofile'
    }
    
    android {
        // No changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile ':baseline-profile"'
    }
    
  5. Genera el perfil ejecutando las tareas de Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile.

  6. Al final de la tarea de generación, el perfil de Baseline se copia en app/src/variant/generated/baselineProfiles.

Cómo crear un nuevo Perfil de Baseline con AGP 7.3-7.4

Es posible generar perfiles de Baseline con AGP 7.3-7.4, pero te recomendamos que lo actualices a AGP 8.1, como mínimo, para que puedas usar el complemento de Gradle para perfiles de Baseline y sus funciones más recientes.

Si necesitas crear perfiles de Baseline con AGP 7.3-7.4, los pasos son los mismos que los pasos para AGP 8.1, con las siguientes excepciones:

Cómo aplicar de forma manual las reglas generadas

El generador de Perfiles de Baseline crea un archivo de texto con formato legible por humanos (HRF) en el dispositivo y lo copia en la máquina anfitrión. Sigue estos pasos para aplicar el perfil generado a tu código:

  1. Ubica el archivo HRF en la carpeta de compilación del módulo en el que generas el perfil: [module]/build/outputs/managed_device_android_test_additional_output/[device].

    Los perfiles siguen el patrón de nomenclatura [class name]-[test method name]-baseline-prof.txt, que tiene este aspecto: BaselineProfileGenerator-startup-baseline-prof.txt.

  2. Copia el perfil generado en src/main/ y cambia el nombre del archivo a baseline-prof.txt.

  3. Agrega una dependencia a la biblioteca de ProfileInstaller en el archivo build.gradle.kts de tu app para habilitar la compilación de perfiles de Baseline locales donde no estén disponibles los perfiles de Cloud. Esta es la única manera de transferir un perfil de Baseline de forma local.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.3.1")
    }
    
  4. Compila la versión de producción de tu app mientras que las reglas de HRF aplicadas se compilan en formato binario y se incluyen en el APK o el AAB. Luego, distribuye tu app como de costumbre.

Cómo obtener comparativas del perfil de Baseline

Para obtener comparativas de tu perfil de Baseline, crea una nueva configuración para la ejecución de pruebas de instrumentación de Android a partir de la acción del margen que ejecuta las comparativas definidas en el archivo StartupBenchmarks.kt o StartupBencharks.java. Si quieres obtener más información sobre las pruebas de comparativas, consulta Cómo crear una clase de Macrobenchmark y Cómo automatizar la medición con la biblioteca de Macrobenchmark.

Figura 3: Ejecuta las Pruebas de Android desde la acción del margen.

Cuando ejecutas esto en Android Studio, el resultado de la compilación contiene detalles de las mejoras de velocidad que proporciona el perfil de Baseline:

StartupBenchmarks_startupCompilationBaselineProfiles
timeToInitialDisplayMs   min 161.8,   median 178.9,   max 194.6
StartupBenchmarks_startupCompilationNone
timeToInitialDisplayMs   min 184.7,   median 196.9,   max 202.9

Cómo capturar todas las instrucciones de código obligatorias

Las dos métricas clave para medir los tiempos de inicio de la app son las siguientes:

Tiempo para la visualización inicial (TTID)
Se trata del tiempo que lleva mostrar el primer fotograma de la IU de la aplicación.
Tiempo para la visualización completa (TTFD)
Se trata del TTID más el tiempo para mostrar contenido que se carga, de forma asíncrona, después de que se muestra el fotograma inicial.

El TTFD se informa una vez que se llama al método reportFullyDrawn() de la ComponentActivity. Si nunca se llama a reportFullyDrawn(), se informa el TTID en su lugar. Es posible que debas retrasar el momento en que se llama a reportFullyDrawn() hasta que se complete la carga asíncrona. Por ejemplo, si la IU contiene una lista dinámica, como una RecyclerView o una lista diferida, que podría completarse con una tarea en segundo plano que finaliza después de que se obtiene la lista por primera vez y, por lo tanto, después de que la IU se marca como obtenida por completo. En esos casos, el código que se ejecuta después de que la IU alcanza el estado de obtenida por completo no se incluye en el perfil de Baseline.

Para incluir la propagación de la lista como parte de tu perfil de Baseline, obtén FullyDrawnReporter con getFullyDrawnReporter() y agrégale un generador de informes en el código de la app. Lanza el generador de informes una vez que la tarea en segundo plano termine de completar la lista. FullyDrawnReporter no llama al método reportFullyDrawn() hasta que se lanzan todos los generadores de informes. De esta manera, el perfil de Baseline incluye las instrucciones de código necesarias para completar la lista. Esto no cambia el comportamiento de la app para el usuario, pero permite que el perfil de Baseline incluya todas las instrucciones de código necesarias.

Si tu app usa Jetpack Compose, usa las siguientes APIs para indicar el estado de obtenida por completo:

  • ReportDrawn: Indica que el elemento componible está listo de inmediato para interactuar.
  • ReportDrawnWhen: Toma un predicado, como list.count > 0, para indicar cuándo el elemento componible está listo para interactuar.
  • ReportDrawnAfter: Toma un método de suspensión que, cuando se completa, indica que el elemento componible está listo para la interacción.