Creare profili di riferimento

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

Di seguito sono riportati i passaggi generali per creare un nuovo profilo di riferimento:

  1. Impostare il modulo Profilo di riferimento.
  2. Definisci il test JUnit che consente di generare profili di riferimento.
  3. Aggiungi i percorsi dell'utente critici (CUJ) che vuoi ottimizzare.
  4. Genera il profilo di baseline.

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

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

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

Il modello di modulo Generatore di profili di riferimento di Android Studio automatizza la creazione di un nuovo modulo per generare e eseguire il benchmark dei profili di riferimento. L'esecuzione del modello genera la maggior parte della configurazione di compilazione tipica, della generazione del profilo di riferimento e del codice di verifica. Il modello crea codice per generare e confrontare i profili di riferimento per misurare l'avvio dell'app.

Configurare il modulo Profilo di riferimento

Per eseguire il modello di modulo Profilo di riferimento:

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

    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, questo elenco contiene un solo elemento.
    • Nome del modulo: il nome che vuoi assegnare al modulo Profilo di riferimento in fase di creazione.
    • Nome del pacchetto: il nome del pacchetto che vuoi per il modulo Profilo di riferimento.
    • Lingua: indica se vuoi che il codice generato sia in Kotlin o Java.
    • Linguaggio di configurazione build: se vuoi utilizzare lo script Kotlin (KTS) o Groovy per gli script di configurazione della build.
    • Utilizza un dispositivo gestito da Gradle: indica se utilizzi dispositivi gestiti da Gradle per testare la tua app.
  3. Fai clic su Fine per creare il nuovo modulo. Se utilizzi il controllo del codice sorgente, è possibile che ti venga richiesto di aggiungere i file dei moduli appena creati al controllo dell'origine.

Definisci il generatore del profilo di riferimento

Il modulo appena creato contiene test per generare e eseguire il benchmark del profilo di riferimento e testare solo l'avvio di base dell'app. Ti consigliamo di aumentarli in modo da includere CUJ e flussi di lavoro avanzati per le startup. Assicurati che tutti i test correlati all'avvio dell'app siano in un blocco rule con includeInStartupProfile impostato su true. In caso contrario, per un rendimento ottimale, assicurati che tutti i test non correlati 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 riferimento chiamata profilo di avvio.

È utile per la manutenibilità se estrai questi CUJ dal profilo di riferimento e dal codice di benchmark generati in modo che possano essere utilizzati per entrambi. Ciò significa che le modifiche ai CUJ vengono utilizzate in modo coerente.

Genera e installa il profilo di baseline

Il modello del modulo Profilo di baseline aggiunge una nuova configurazione di esecuzione per generare il profilo di baseline. Se utilizzi i flavor dei prodotti, Android Studio crea più configurazioni di esecuzione in modo da poter generare profili di riferimento distinti per ogni flavor.

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

Una volta completata la configurazione di esecuzione Generate Baseline Profile, il profilo di base generato viene copiato nel file src/variant/generated/baselineProfiles/baseline-prof.txt nel modulo che viene profilato. Le opzioni di variante sono il tipo di build di release o una variante di build che coinvolge il tipo di build di release.

Il profilo di baseline generato è stato creato originariamente in build/outputs. Il percorso completo è dettato dalla variante o dal flavor dell'app di cui viene eseguito il profiling e dal fatto che tu utilizzi un dispositivo gestito da Gradle o un dispositivo connesso per il profiling. Se utilizzi i nomi utilizzati dal codice e dalle configurazioni di build generate dal modello, il profilo di riferimento 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 riferimento generato a meno che tu non lo stia copiando manualmente nei moduli di destinazione (non consigliato).

Creare un nuovo profilo di riferimento con AGP 8.1

Se non riesci a utilizzare il modello di modulo Baseline Profile, 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 riferimento utilizzando il modello di modulo Macrobenchmark e il plug-in Gradle del profilo di riferimento:

  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. In questo modo puoi ottimizzare le prestazioni di runtime della tua app, ad esempio elenchi di scorrimento, esecuzione di animazioni e navigazione all'interno di Activity. Scopri altri esempi di test che utilizzano @BaselineProfileRule per migliorare i percorsi degli utenti critici.

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

  4. Per generare il profilo di riferimento, esegui le attività Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile nel terminale.

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

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

Creare un nuovo profilo di riferimento senza modelli

Ti consigliamo di creare un profilo di base utilizzando il modello di modulo Baseline Profile (preferito) o il modello Macrobenchmark di Android Studio, ma puoi anche utilizzare il plug-in Gradle del profilo di base. Per scoprire di più sul plug-in Gradle del profilo di riferimento, consulta Configurare la generazione del profilo di riferimento.

Ecco come creare un profilo di riferimento utilizzando direttamente il plug-in Gradle del profilo di riferimento:

  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 indichi il modulo :app.
    3. Se vuoi, aggiungi un dispositivo gestito da Gradle (GMD). Nell'esempio seguente è pixel6Api31. Se non specificato, il plug-in utilizza un dispositivo connesso, virtuale 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 riferimento nel :baseline-profile modulo di test. L'esempio seguente è un test che avvia l'app e attende lo stato inattivo.

    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"))
    }

    Alla moda

    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 le attività Gradle :app:generateBaselineProfile o :app:generateVariantBaselineProfile.

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

Creare un nuovo profilo di riferimento con AGP 7.3-7.4

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

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

Applicare manualmente le regole generate

Il generatore di profili di riferimento crea un file di testo in formato leggibile dall'uomo (HRF) sul dispositivo e lo copia sulla macchina host. Per applicare il profilo generato al tuo codice:

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

    I profili seguono lo schema 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 dell'app per abilitare la compilazione del profilo di base locale, dove i profili Cloud non sono disponibili. Questo è l'unico modo per eseguire il sideload di un profilo di baseline a livello locale.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. Crea la versione di produzione dell'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.

Eseguire il benchmark del profilo di riferimento

Per eseguire un benchmark del tuo profilo di base, crea una nuova configurazione di Android Instrumented Test Run dall'azione gutter che esegue i benchmark definiti nel file StartupBenchmarks.kt o StartupBencharks.java. Per scoprire di più sul test di benchmark, consulta Creare una classe Macrobenchmark e Automatizzare la misurazione con la libreria Macrobenchmark.

Figura 3. Esegui i test Android dall'azione della grondaia.

Quando lo esegui 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

Acquisisci 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 dell'interfaccia utente dell'applicazione.
Tempo di attesa per la visualizzazione completa (TTFD)
TTID più il tempo necessario per la visualizzazione dei contenuti, che vengono caricati in modo asincrono dopo la visualizzazione del frame iniziale.

Il TTFD viene registrato una volta chiamato il metodo reportFullyDrawn() del ComponentActivity. Se reportFullyDrawn() non viene mai chiamato, viene registrato il valore TTID. Potresti dover ritardare l'esecuzione di reportFullyDrawn() fino al completamento del caricamento asincrono. Ad esempio, se l'interfaccia utente contiene un elenco dinamico come RecyclerView o un elenco lazy, l'elenco potrebbe essere compilato da un'attività in background che viene completata dopo la prima visualizzazione dell'elenco e, di conseguenza, dopo che l'interfaccia utente è contrassegnata come completamente visualizzata. In questi casi, il codice eseguito dopo che l'interfaccia utente raggiunge lo stato di disegno completo non è incluso nel profilo di riferimento.

Per includere la popolazione dell'elenco nel tuo profilo di riferimento, ottieni il valore FullyDrawnReporter utilizzando getFullyDrawnReporter() e aggiungi un reporter al codice dell'app. Rilascia il report quando l'attività in background ha completato il completamento dell'elenco. FullyDrawnReporter non chiama il metodo reportFullyDrawn() finché non vengono rilasciati tutti i reporter. In questo modo, il profilo di riferimento include i percorsi di codice necessari per compilare l'elenco. Ciò non modifica il comportamento dell'app per l'utente, ma consente al profilo di riferimento di includere tutti i percorsi di codice necessari.

Se la tua app utilizza Jetpack Compose, usa le seguenti API per indicare lo stato completamente disegnato:

  • ReportDrawn indica che il composable è immediatamente pronto per l'interazione.
  • ReportDrawnWhen utilizza un predicato, ad esempio list.count > 0, per indicare quando l'elemento componibile è pronto per l'interazione.
  • ReportDrawnAfter utilizza un metodo di sospensione che, una volta completato, indica che l'elemento componibile è pronto per l'interazione.