Creare profili di riferimento

Genera automaticamente profili per ogni release dell'app utilizzando la libreria Jetpack Macrobenchmark e BaselineProfileRule. Ti consigliamo di utilizzare com.android.tools.build:gradle:8.0.0 o versioni successive, che includono miglioramenti della build quando utilizzi i profili di base.

Ecco i passaggi generali per creare un nuovo profilo di base:

  1. Configura il modulo Profilo di base.
  2. Definisci il test JUnit che consente di generare profili di base.
  3. Aggiungi i Critical User Journey (CUJ) che vuoi ottimizzare.
  4. Genera il profilo di base.

Dopo aver generato il profilo di base, esegui il benchmark utilizzando un dispositivo fisico per misurare i miglioramenti della velocità.

Crea un nuovo profilo di base con AGP 8.2 o versioni successive

Il modo più semplice per creare un nuovo profilo di base è utilizzare il modello di modulo del profilo di base, disponibile a partire da Android Studio Iguana e Android Gradle Plugin (AGP) 8.2.

Il modello di modulo Android Studio Baseline Profile Generator automatizza la creazione di un nuovo modulo per generare e confrontare i profili di base. L'esecuzione del modello genera la maggior parte della configurazione di build tipica, la generazione del profilo di base e il codice di verifica. Il modello crea codice per generare e confrontare i profili di base per misurare l'avvio dell'app.

Configurare il modulo Profilo di base

Per eseguire il modello di modulo Profilo di base:

  1. Seleziona File > Nuovo > Nuovo modulo.
  2. Seleziona il modello Generatore di profili di base nel riquadro Modelli e configuralo:
    Figura 1. Modello del modulo Generatore di profili di base.

    I campi nel modello sono i seguenti:

    • Applicazione di destinazione: definisce per quale app viene generato il profilo di base. Se il progetto contiene un solo modulo dell'app, l'elenco contiene un solo elemento.
    • Nome modulo: il nome che vuoi assegnare al modulo del profilo di base che viene creato.
    • Nome pacchetto: il nome del pacchetto che vuoi per il modulo del profilo di base.
    • Linguaggio: se vuoi che il codice generato sia Kotlin o Java.
    • Linguaggio di configurazione della build: indica se vuoi utilizzare Kotlin Script (KTS) o Groovy per gli script di configurazione della build.
    • Utilizza il dispositivo gestito da Gradle: indica se utilizzi dispositivi gestiti da Gradle per testare la tua app.
  3. Fai clic su Fine e il nuovo modulo viene creato. Se utilizzi il controllo del codice sorgente, potrebbe esserti chiesto di aggiungere i file del modulo appena creato al controllo del codice sorgente.

Definisci il generatore di profili di base

Il modulo appena creato contiene test per generare e confrontare il profilo di base e testare solo l'avvio di base dell'app. Ti consigliamo di ampliare questi elementi per includere i CUJ e i workflow di avvio avanzati. Assicurati che tutti i test relativi all'avvio dell'app si trovino in un blocco rule con includeInStartupProfile impostato su true; al contrario, per prestazioni ottimali, assicurati che tutti i test non relativi all'avvio dell'app non siano inclusi in un profilo di avvio. Le ottimizzazioni dell'avvio dell'app vengono utilizzate per definire una parte speciale di un profilo di base chiamata profilo di avvio.

Aiuta a mantenere la manutenibilità se estrai questi CUJ al di fuori del codice del profilo di base e del benchmark generati, in modo che possano essere utilizzati per entrambi. Ciò significa che le modifiche alle tue CUJ vengono utilizzate in modo coerente.

Genera e installa il profilo di base

Il modello di modulo Baseline Profile aggiunge una nuova configurazione di esecuzione per generare il profilo di base. Se utilizzi le varianti del prodotto, Android Studio crea più configurazioni di esecuzione in modo da poter generare profili di base separati per ogni variante.

La configurazione di esecuzione Genera profilo di base.
Figura 2. L'esecuzione di questa configurazione genera il profilo di base.

Al termine della configurazione di esecuzione Genera profilo di base, il profilo di base generato viene copiato nel file src/variant/generated/baselineProfiles/baseline-prof.txt del modulo di cui viene eseguito il profiling. Le opzioni di variante sono il tipo di build di rilascio o una variante di build che include il tipo di build di rilascio.

Il profilo di base generato è stato creato originariamente in build/outputs. Il percorso completo è determinato dalla variante o dalla versione dell'app di cui viene creato il profilo e dal fatto che utilizzi un dispositivo gestito da Gradle o un dispositivo connesso per la profilazione. Se utilizzi i nomi utilizzati dalle configurazioni di codice e build generate dal modello, il profilo di base viene creato nel file build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. Probabilmente non dovrai interagire direttamente con questa versione del profilo di base generato a meno che tu non la copi manualmente nei moduli di destinazione (non consigliato).

Crea un nuovo profilo di base con AGP 8.1

Se non riesci a utilizzare il modello di modulo del profilo di base, utilizza il modello di modulo Macrobenchmark e il plug-in Gradle del profilo di base per creare un nuovo profilo di base. Ti consigliamo di utilizzare questi strumenti a partire da Android Studio Giraffe e AGP 8.1.

Ecco i passaggi per creare un nuovo profilo di base utilizzando il modello di modulo Macrobenchmark e il plug-in Gradle per il profilo di base:

  1. Configura un modulo Macrobenchmark nel tuo progetto Gradle.
  2. Definisci una nuova classe denominata BaselineProfileGenerator:
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }

    Il generatore può contenere interazioni con la tua app oltre all'avvio dell'app. In questo modo puoi ottimizzare le prestazioni di runtime della tua app, ad esempio scorrere gli elenchi, eseguire animazioni e navigare all'interno di un Activity. Visualizza altri esempi di test che utilizzano @BaselineProfileRule per migliorare i percorsi utente critici.

  3. Aggiungi il plug-in Gradle per i profili di base (libs.plugins.androidx.baselineprofile). Il plug-in semplifica la generazione e la manutenzione dei profili di base in futuro.

  4. Per generare il profilo di base, esegui i task Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile nel terminale.

    Esegui il generatore come test strumentato su un dispositivo fisico con accesso root, un emulatore o un dispositivo gestito da Gradle. Se utilizzi un dispositivo gestito da Gradle, imposta aosp come systemImageSource, perché hai bisogno dell'accesso root per il generatore di profili di base.

    Al termine dell'attività di generazione, il profilo di base viene copiato in app/src/variant/generated/baselineProfiles.

Crea un nuovo profilo di base senza modelli

Ti consigliamo di creare un profilo di base utilizzando il modello di modulo Profilo di base di Android Studio (opzione preferita) o il modello Macrobenchmark, ma puoi anche utilizzare il plug-in Gradle del profilo di base da solo. Per saperne di più sul plug-in Gradle per i profili di base, consulta Configurare la generazione dei profili di base.

Ecco come creare un profilo di base utilizzando direttamente il plug-in Gradle per i profili di base:

  1. Crea un nuovo modulo com.android.test, ad esempio :baseline-profile.
  2. Configura il file build.gradle.kts per :baseline-profile:

    1. Applica il plug-in androidx.baselineprofile.
    2. Assicurati che targetProjectPath punti al modulo :app.
    3. (Facoltativo) Aggiungi un dispositivo gestito da Gradle (GMD). Nell'esempio seguente, è pixel6Api31. Se non specificato, il plug-in utilizza un dispositivo connesso, emulato o fisico.
    4. Applica la configurazione che preferisci, come mostrato nell'esempio seguente.

    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 un test del profilo di base nel modulo di test :baseline-profile. L'esempio seguente è un test che avvia l'app e attende che sia inattiva.

    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. Aggiorna il file build.gradle.kts nel modulo dell'app, ad esempio :app.

    1. Applica il plug-in androidx.baselineprofile.
    2. Aggiungi una dipendenza baselineProfile al modulo :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 il profilo eseguendo i task Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile.

  6. Al termine dell'attività di generazione, il profilo di base viene copiato in app/src/variant/generated/baselineProfiles.

Crea un nuovo profilo di base con AGP 7.3-7.4

È possibile generare profili di base con AGP 7.3-7.4, ma ti consigliamo vivamente di eseguire l'upgrade ad almeno AGP 8.1 per poter utilizzare il plug-in Gradle per i profili di base e le sue funzionalità più recenti.

Se devi creare profili di base con AGP 7.3-7.4, i passaggi sono gli stessi dei passaggi per AGP 8.1, con le seguenti eccezioni:

Applicare manualmente le regole generate

Il generatore di profili di base crea un file di testo in formato leggibile (HRF) sul dispositivo e lo copia sulla macchina host. Per applicare il profilo generato al tuo codice, segui questi passaggi:

  1. Individua il file HRF nella cartella di build del modulo in cui generi il profilo: [module]/build/outputs/managed_device_android_test_additional_output/[device].

    I profili seguono il pattern di denominazione [class name]-[test method name]-baseline-prof.txt, che ha il seguente aspetto: BaselineProfileGenerator-startup-baseline-prof.txt.

  2. Copia il profilo generato in src/main/ e rinomina il file in baseline-prof.txt.

  3. Aggiungi una dipendenza alla libreria ProfileInstaller nel file build.gradle.kts della tua app per attivare la compilazione del profilo di base locale quando i profili cloud non sono disponibili. Questo è l'unico modo per caricare in locale un profilo di base.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. Crea la versione di produzione della tua app mentre le regole HRF applicate vengono compilate in formato binario e incluse nell'APK o nell'AAB. Poi distribuisci la tua app come di consueto.

Benchmark del profilo di base

Per eseguire il benchmark del profilo di base, crea una nuova configurazione di esecuzione del test strumentato Android dall'azione del margine che esegue i benchmark definiti nel file StartupBenchmarks.kt o StartupBencharks.java. Per scoprire di più sui test di benchmark, consulta Creare una classe Macrobenchmark e Automatizzare la misurazione con la libreria Macrobenchmark.

Figura 3. Esegui test Android dall'azione del margine.

Quando esegui questa operazione in Android Studio, l'output della build contiene i dettagli dei miglioramenti della velocità forniti dal profilo di base:

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

Acquisire tutti i percorsi di codice richiesti

Le due metriche chiave per misurare i tempi di avvio delle app sono le seguenti:

Tempo di attesa per la prima schermata (TTID)
Il tempo necessario per visualizzare il primo frame della UI dell'applicazione.
Tempo di attesa per la visualizzazione completa (TTFD)
TTID più il tempo necessario per visualizzare i contenuti caricati in modo asincrono dopo la visualizzazione del frame iniziale.

TTFD viene segnalato una volta chiamato il metodo reportFullyDrawn() di ComponentActivity. Se reportFullyDrawn() non viene mai chiamato, viene segnalato il TTID. Potresti dover ritardare la chiamata di reportFullyDrawn() fino al completamento del caricamento asincrono. Ad esempio, se la UI contiene un elenco dinamico come un RecyclerView o un elenco pigro, l'elenco potrebbe essere compilato da un'attività in background che viene completata dopo il primo disegno dell'elenco e, pertanto, dopo che la UI è contrassegnata come completamente disegnata. In questi casi, il codice eseguito dopo che la UI raggiunge lo stato completamente disegnato non è incluso nel profilo di base.

Per includere il popolamento dell'elenco nel tuo profilo di base, recupera FullyDrawnReporter utilizzando getFullyDrawnReporter() e aggiungi un reporter nel codice dell'app. Rilascia il reporter una volta che l'attività in background ha terminato di compilare l'elenco. FullyDrawnReporter non chiama il metodo reportFullyDrawn() finché non vengono rilasciati tutti i reporter. In questo modo, il profilo di base include i percorsi del codice necessari per compilare l'elenco. Ciò non modifica il comportamento dell'app per l'utente, ma consente al profilo di base di includere tutti i percorsi di codice necessari.

Se la tua app utilizza Jetpack Compose, utilizza le seguenti API per indicare lo stato di disegno completo:

  • ReportDrawn indica che il composable è immediatamente pronto per l'interazione.
  • ReportDrawnWhen accetta un predicato, ad esempio list.count > 0, per indicare quando il componente componibile è pronto per l'interazione.
  • ReportDrawnAfter accetta un metodo di sospensione che, al termine, indica che il componente componibile è pronto per l'interazione.