1. Prima di iniziare
Questo codelab mostra come generare profili di base per ottimizzare le prestazioni della tua applicazione e come verificare i vantaggi in termini di prestazioni dell'utilizzo dei profili di base.
Che cosa ti serve
- Android Studio Hedgehog (2023.1.1) o versioni successive
- Plug-in Android per Gradle 8.0 o versioni successive
- Conoscenza di base di Jetpack Macrobenchmark
- Un dispositivo Android fisico con Android 7 (livello API 24) o versioni successive
In questo lab proverai a:
- Configura il progetto per utilizzare i generatori di profili di base.
- Genera profili di baseline per ottimizzare l'avvio dell'app e le prestazioni di scorrimento.
- Verifica i miglioramenti delle prestazioni con la libreria Jetpack Macrobenchmark.
Obiettivi didattici
- Profili di base e come possono migliorare le prestazioni dell'app.
- Come generare profili di base.
- Miglioramenti delle prestazioni dei profili di base.
2. Preparazione
Per iniziare, clona il repository GitHub dalla riga di comando utilizzando il seguente comando:
$ git clone https://github.com/android/codelab-android-performance.git
In alternativa, puoi scaricare due file ZIP:
Apri progetto in Android Studio
- Nella finestra di benvenuto di Android Studio, seleziona
Apri un progetto esistente. - Seleziona la cartella
[Download Location]/codelab-android-performance/baseline-profiles. Assicurati di selezionare la directorybaseline-profiles. - Quando Android Studio importa il progetto, assicurati di poter eseguire il modulo
appper creare l'applicazione di esempio con cui lavorerai in seguito.
L'app di esempio
In questo codelab, lavorerai con l'applicazione di esempio JetSnack. È un'app virtuale per ordinare snack che utilizza Jetpack Compose.
Per misurare il rendimento dell'applicazione, devi comprendere la struttura della UI e il comportamento dell'app, in modo da poter accedere agli elementi della UI dai benchmark. Esegui l'app e acquisisci familiarità con le schermate di base ordinando degli snack. Non è necessario conoscere i dettagli dell'architettura dell'app.

3. Che cosa sono i profili di baseline
I profili di base migliorano la velocità di esecuzione del codice di circa il 30% dal primo avvio evitando i passaggi di interpretazione e compilazione just-in-time (JIT) per i percorsi di codice inclusi. Se includi un profilo di base in un'app o in una libreria, Android Runtime (ART) può ottimizzare i percorsi di codice inclusi tramite la compilazione Ahead of Time (AOT), migliorando le prestazioni per ogni nuovo utente e a ogni aggiornamento dell'app. Questa ottimizzazione guidata dal profilo (PGO) consente alle app di ottimizzare l'avvio, ridurre i problemi di interazione e migliorare le prestazioni complessive di runtime per gli utenti finali fin dal primo avvio.
Con un profilo di base, tutte le interazioni dell'utente, come l'avvio dell'app, la navigazione tra le schermate o lo scorrimento dei contenuti, sono più fluide fin dalla prima esecuzione. L'aumento della velocità e della reattività di un'app porta a un maggior numero di utenti attivi giornalieri e a un tasso di ritorno medio più elevato.
I profili di base aiutano a guidare l'ottimizzazione oltre l'avvio dell'app fornendo interazioni comuni degli utenti che migliorano l'esecuzione dell'app dal primo avvio. La compilazione AOT guidata non si basa sui dispositivi degli utenti e può essere eseguita una volta per release su un computer di sviluppo anziché su un dispositivo mobile. Se pubblichi release con un profilo di base, le ottimizzazioni delle app diventano disponibili molto più rapidamente rispetto a quando si utilizzano solo i profili cloud.
Quando non viene utilizzato un profilo di base, tutto il codice dell'app viene compilato JIT in memoria dopo essere stato interpretato o in un file odex in background quando il dispositivo è inattivo. Gli utenti potrebbero quindi avere un'esperienza non ottimale quando eseguono un'app dopo averla installata o aggiornata per la prima volta prima che i nuovi percorsi vengano ottimizzati.
4. Configurare il modulo generatore di profili di base
Puoi generare profili di base con una classe di test di strumentazione che richiede l'aggiunta di un nuovo modulo Gradle al tuo progetto. Il modo più semplice per aggiungerlo al tuo progetto è utilizzare la procedura guidata per i moduli di Android Studio inclusa in Android Studio Hedgehog o versioni successive.
Apri la finestra della procedura guidata per il nuovo modulo facendo clic con il tasto destro del mouse sul progetto o sul modulo nel riquadro Progetto e selezionando Nuovo > Modulo.

Nella finestra aperta, seleziona Baseline Profile Generator (Generatore di profili di base) nel riquadro Modelli.

Oltre ai soliti parametri come nome del modulo, nome del pacchetto, lingua o lingua di configurazione della build, ci sono due input che non sono comuni per un nuovo modulo: Applicazione di destinazione e Usa dispositivo gestito da Gradle.
L'applicazione di destinazione è il modulo dell'app utilizzato per generare i profili di base. Se il tuo progetto contiene più di un modulo dell'app, seleziona quello per cui vuoi eseguire i generatori.
La casella di controllo Utilizza dispositivo gestito da Gradle imposta il modulo per eseguire i generatori di profili di base su emulatori Android gestiti automaticamente. Puoi scoprire di più sui dispositivi gestiti da Gradle in Scalare i test con i dispositivi gestiti da Gradle. Se deselezioni questa casella, i generatori utilizzano qualsiasi dispositivo connesso.
Una volta definiti tutti i dettagli del nuovo modulo, fai clic su Fine per procedere con la creazione del modulo.
Modifiche apportate dalla procedura guidata del modulo
La procedura guidata per i moduli apporta diverse modifiche al progetto.
Aggiunge un modulo Gradle denominato baselineprofile o il nome che selezioni nella procedura guidata.
Questo modulo utilizza il plug-in com.android.test, che indica a Gradle di non includerlo nell'applicazione, pertanto può contenere solo codice di test o benchmark. Applica anche il plug-in androidx.baselineprofile, che consente di automatizzare la generazione dei profili di base.
La procedura guidata apporta modifiche anche al modulo dell'applicazione di destinazione selezionato. Nello specifico, applica il plug-in androidx.baselineprofile, aggiunge la dipendenza androidx.profileinstaller e la dipendenza baselineProfile al modulo build.gradle(.kts) appena creato:
plugins {
id("androidx.baselineprofile")
}
dependencies {
// ...
implementation("androidx.profileinstaller:profileinstaller:1.3.0")
"baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}
L'aggiunta della dipendenza androidx.profileinstaller ti consente di:
- Verifica localmente i miglioramenti delle prestazioni dei profili di base generati.
- Utilizza i profili di base su Android 7 (livello API 24) e Android 8 (livello API 26), che non supportano i profili cloud.
- Utilizza i profili di base sui dispositivi che non dispongono di Google Play Services.
La dipendenza baselineProfile(project(":baselineprofile")) consente a Gradle di sapere da quale modulo deve prendere i profili di base generati.
Ora che hai impostato il progetto, scrivi una classe generatore di profili di base.
5. Scrivere un generatore di profili di base
In genere, generi profili di base per i percorsi utente tipici della tua app.
La procedura guidata del modulo crea una classe di test BaselineProfileGenerator di base in grado di generare il profilo di base per l'avvio dell'app e ha il seguente aspetto:
@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {
@get:Rule
val rule = BaselineProfileRule()
@Test
fun generate() {
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
// 2. Scroll the feed content.
// 3. Navigate to detail screen.
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
}
}
Questa classe utilizza una regola di test BaselineProfileRule e contiene un metodo di test per generare il profilo. Il punto di ingresso per la generazione del profilo è la funzione collect(). Richiede solo due parametri:
packageName: il pacchetto della tua app.profileBlock: l'ultimo parametro lambda.
Nella lambda profileBlock, specifichi le interazioni che coprono i percorsi utente tipici della tua app. La libreria esegue profileBlock più volte, raccoglie le classi e le funzioni chiamate e genera il profilo di base sul dispositivo con il codice da ottimizzare.
Per impostazione predefinita, la classe del generatore creata contiene interazioni per avviare l'intent predefinito Activity e attende che venga eseguito il rendering del primo frame dell'app utilizzando il metodo startActivityAndWait().
Estendere il generatore con percorsi personalizzati
Puoi notare che la classe generata include anche alcuni TODO per scrivere altre interazioni per ottimizzare i percorsi avanzati della tua app. Questa operazione è consigliata per ottimizzare il rendimento oltre l'avvio dell'app.
Nella nostra app di esempio, puoi identificare questi percorsi nel seguente modo:
- Avvia l'applicazione. Questo aspetto è già parzialmente coperto dalla classe generata.
- Attendi il caricamento asincrono dei contenuti.
- Scorri l'elenco degli snack.
- Vai ai dettagli dello snack.
Modifica il generatore in modo che contenga le funzioni descritte che coprono i percorsi tipici nello snippet seguente:
// ...
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
waitForAsyncContent()
// 2. Scroll the feed content.
scrollSnackListJourney()
// 3. Navigate to detail screen.
goToSnackDetailJourney()
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
// ...
Ora scrivi le interazioni per ogni percorso menzionato. Puoi scriverlo come funzione di estensione di MacrobenchmarkScope per avere accesso ai parametri e alle funzioni che fornisce. In questo modo, puoi riutilizzare le interazioni con i benchmark per verificare i miglioramenti del rendimento.
Attendi i contenuti asincroni
Molte app hanno un caricamento asincrono all'avvio, noto anche come stato di visualizzazione completa, che indica al sistema quando i contenuti vengono caricati e visualizzati e quando l'utente può interagire con loro. Attendi lo stato nel generatore (waitForAsyncContent) con queste interazioni:
- Trova l'elenco degli snack del feed.
- Attendi che alcuni elementi dell'elenco siano visibili sullo schermo.
fun MacrobenchmarkScope.waitForAsyncContent() {
device.wait(Until.hasObject(By.res("snack_list")), 5_000)
val contentList = device.findObject(By.res("snack_list"))
// Wait until a snack collection item within the list is rendered.
contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)
}
Percorso dell'elenco scorrevole
Per il percorso dell'elenco di snack scorrevole (scrollSnackListJourney), puoi seguire queste interazioni:
- Trova l'elemento dell'interfaccia utente dell'elenco degli snack.
- Imposta i margini dei gesti in modo da non attivare la navigazione del sistema.
- Scorri l'elenco e attendi che l'interfaccia utente si stabilizzi.
fun MacrobenchmarkScope.scrollSnackListJourney() {
val snackList = device.findObject(By.res("snack_list"))
// Set gesture margin to avoid triggering gesture navigation.
snackList.setGestureMargin(device.displayWidth / 5)
snackList.fling(Direction.DOWN)
device.waitForIdle()
}
Vai al percorso dettagliato
L'ultimo percorso (goToSnackDetailJourney) implementa queste interazioni:
- Trova l'elenco degli snack e tutti gli elementi degli snack con cui puoi lavorare.
- Seleziona un elemento dall'elenco.
- Fai clic sull'elemento e attendi il caricamento della schermata dei dettagli. Puoi sfruttare il fatto che l'elenco degli snack non sarà più sullo schermo.
fun MacrobenchmarkScope.goToSnackDetailJourney() {
val snackList = device.findObject(By.res("snack_list"))
val snacks = snackList.findObjects(By.res("snack_item"))
// Select snack from the list based on running iteration.
val index = (iteration ?: 0) % snacks.size
snacks[index].click()
// Wait until the screen is gone = the detail is shown.
device.wait(Until.gone(By.res("snack_list")), 5_000)
}
Dopo aver definito tutte le interazioni necessarie per l'esecuzione del generatore di profili di base, devi definire il dispositivo su cui viene eseguito.
6. Preparare un dispositivo su cui eseguire il generatore
Per generare profili di base, ti consigliamo di utilizzare un emulatore come un dispositivo gestito da Gradle o un dispositivo con Android 13 (API 33) o versioni successive.
Per rendere riproducibile il processo e automatizzare la generazione dei profili di base, puoi utilizzare i dispositivi gestiti da Gradle. I dispositivi gestiti da Gradle ti consentono di eseguire test su un emulatore Android senza doverlo avviare e chiudere manualmente. Puoi scoprire di più sui dispositivi gestiti da Gradle in Scalare i test con i dispositivi gestiti da Gradle.
Per definire un dispositivo gestito da Gradle, aggiungi la relativa definizione al file build.gradle.kts del modulo :baselineprofile come mostrato nello snippet seguente:
android {
// ...
testOptions.managedDevices.devices {
create<ManagedVirtualDevice>("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
In questo caso, utilizziamo Android 11 (livello API 31) e l'immagine di sistema aosp è in grado di accedere come root.
Successivamente, configura il plug-in Gradle del profilo di base per utilizzare il dispositivo gestito da Gradle definito. Per farlo, aggiungi il nome del dispositivo alla proprietà managedDevices e disattiva useConnectedDevices come mostrato nel seguente snippet:
android {
// ...
}
baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
}
dependencies {
// ...
}
A questo punto, genera il profilo di base.
7. Generare il profilo di base
Una volta che il dispositivo è pronto, puoi creare il profilo di base. Il plug-in Gradle per i profili di base crea attività Gradle per automatizzare l'intero processo di esecuzione della classe di test del generatore e di applicazione dei profili di base generati nella tua app.
La nuova procedura guidata del modulo ha creato una configurazione di esecuzione per poter eseguire rapidamente l'attività Gradle con tutti i parametri necessari per l'esecuzione senza dover passare dal terminale ad Android Studio
Per eseguirla, individua la configurazione di esecuzione Generate Baseline Profile e fai clic sul pulsante Esegui
.

L'attività avvia l'immagine dell'emulatore definita in precedenza. Esegui le interazioni dalla classe di test BaselineProfileGenerator più volte, quindi smonta l'emulatore e fornisci l'output ad Android Studio.
Una volta completata l'operazione, il plug-in Gradle inserisce automaticamente il file baseline-prof.txt generato nell'applicazione di destinazione (modulo :app) nella cartella src/release/generated/baselineProfile/.

(Facoltativo) Eseguire il generatore dalla riga di comando
In alternativa, puoi eseguire il generatore dalla riga di comando. Puoi utilizzare l'attività creata da Gradle Managed Device: :app:generateBaselineProfile. Questo comando esegue tutti i test nel progetto definito dalla dipendenza baselineProfile(project(:baselineProfile)). Poiché il modulo contiene anche benchmark per la verifica successiva dei miglioramenti delle prestazioni, questi test non vanno a buon fine e viene visualizzato un avviso relativo all'esecuzione di benchmark su un emulatore.
android .testInstrumentationRunnerArguments .androidx.benchmark.enabledRules=BaselineProfile
A questo scopo, puoi filtrare tutti i generatori di profili di base con il seguente argomento del runner di strumentazione e tutti i benchmark vengono ignorati:
Il comando completo è il seguente:
./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
Distribuire l'app con i profili di base
Una volta generato e copiato il profilo di base nel codice sorgente dell'app, crea la versione di produzione dell'app come di consueto. Non devi fare altro per distribuire i profili di base agli utenti. Vengono selezionate dal plug-in Android per Gradle durante la build e incluse nell'AAB o nell'APK. Dopodiché, carica la build su Google Play.
Quando gli utenti installano l'app o la aggiornano dalla versione precedente, viene installato anche il profilo di base, il che si traduce in un rendimento migliore dalla prima esecuzione dell'app.
Il passaggio successivo mostra come verificare il miglioramento del rendimento dell'app con i profili di base.
8. (Facoltativo) Personalizzare la generazione dei profili di base
Il plug-in Gradle per i profili di base include opzioni per personalizzare la modalità di generazione dei profili in base alle tue esigenze specifiche. Puoi modificare il comportamento con il blocco di configurazione baselineProfile { } negli script di build.
Il blocco di configurazione all'interno del modulo :baselineprofile influisce sul modo in cui eseguire i generatori con la possibilità di aggiungere managedDevices e decidere se utilizzare useConnectedDevices o dispositivi gestiti da Gradle.
Il blocco di configurazione all'interno del modulo di destinazione :app decide dove vengono salvati i profili o come vengono generati. Puoi modificare i seguenti parametri:
automaticGenerationDuringBuild: se abilitato, puoi generare il profilo di base durante la creazione della build di rilascio della produzione. È utile quando crei la CI prima di spedire l'app.saveInSrc: specifica se i profili di base generati vengono archiviati nella cartellasrc/. In alternativa, puoi accedere al file dalla cartella di compilazione:baselineprofile.baselineProfileOutputDir: definisce dove archiviare i profili di base generati.mergeIntoMain: per impostazione predefinita, i profili di base vengono generati per variante di build (variante del prodotto e tipo di build). Se vuoi unire tutti i profili insrc/main, puoi farlo attivando questo flag.filter: puoi filtrare le classi o i metodi da includere o escludere dai profili di base generati. Ciò può essere utile per gli sviluppatori di librerie che vogliono includere solo il codice della libreria.
9. Verificare i miglioramenti delle prestazioni di avvio
Dopo aver generato il profilo di base e averlo aggiunto all'app, verifica che abbia l'effetto desiderato sul rendimento dell'app.
La nuova procedura guidata per i moduli crea una classe di benchmark chiamata StartupBenchmarks. Contiene un benchmark per misurare il tempo di avvio dell'app e lo confronta con quello in cui l'app utilizza i profili di base.
La classe è simile alla seguente:
@RunWith(AndroidJUnit4::class)
@LargeTest
class StartupBenchmarks {
@get:Rule
val rule = MacrobenchmarkRule()
@Test
fun startupCompilationNone() =
benchmark(CompilationMode.None())
@Test
fun startupCompilationBaselineProfiles() =
benchmark(CompilationMode.Partial(BaselineProfileMode.Require))
private fun benchmark(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.COLD,
iterations = 10,
setupBlock = {
pressHome()
},
measureBlock = {
startActivityAndWait()
// TODO Add interactions to wait for when your app is fully drawn.
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
)
}
}
Utilizza MacrobenchmarkRule in grado di eseguire benchmark per la tua app e raccogliere metriche sul rendimento. L'entry point per scrivere un benchmark è la funzione measureRepeated della regola.
Richiede diversi parametri:
packageName:quale applicazione misurare.metrics: il tipo di informazioni che vuoi misurare durante il benchmark.iterations: il numero di ripetizioni del benchmark.startupMode: come vuoi che la tua applicazione venga avviata all'inizio del benchmark.setupBlock: quali interazioni con la tua app devono avvenire prima della misurazione.measureBlock: le interazioni con la tua app che vuoi misurare durante il benchmark.
La classe di test contiene anche due test: startupCompilationeNone() e startupCompilationBaselineProfiles(), che chiamano la funzione benchmark() con compilationMode diversi.
CompilationMode
Il parametro CompilationMode definisce la modalità di precompilazione dell'applicazione in codice macchina. Sono disponibili le seguenti opzioni:
DEFAULT: precompila parzialmente l'app utilizzando i profili di base, se disponibili. Viene utilizzato se non viene applicato alcun parametrocompilationMode.None(): reimposta lo stato di compilazione dell'app e non la precompila. La compilazione just-in-time (JIT) è comunque abilitata durante l'esecuzione dell'app.Partial(): precompila l'app con i profili di base o le esecuzioni di riscaldamento oppure entrambi.Full(): precompila l'intero codice dell'applicazione. Questa è l'unica opzione su Android 6 (API 23) e versioni precedenti.
Se vuoi iniziare a ottimizzare le prestazioni della tua applicazione, puoi scegliere la modalità di compilazione DEFAULT, perché le prestazioni sono simili a quelle che si ottengono quando l'app viene installata da Google Play. Se vuoi confrontare i vantaggi in termini di prestazioni forniti dai profili di base, puoi farlo confrontando i risultati della modalità di compilazione None e Partial.
Modificare il benchmark per attendere i contenuti
I benchmark vengono scritti in modo simile ai generatori di profili di base scrivendo le interazioni con la tua app. Per impostazione predefinita, i benchmark creati attendono solo il rendering del primo frame, in modo simile a quanto fatto da BaselineProfileGenerator, pertanto ti consigliamo di migliorarlo in modo che attenda i contenuti asincroni.
Puoi farlo riutilizzando le funzioni di estensione che scrivi per il generatore. Poiché questo benchmark acquisisce i tempi di avvio utilizzando StartupTimingMetric(), ti consigliamo di includere qui solo l'attesa dei contenuti asincroni e di scrivere un benchmark separato per gli altri percorsi utente definiti nel generatore.
// ...
measureBlock = {
startActivityAndWait()
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
waitForAsyncContent() // <------- Added to wait for async content.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
Esegui i benchmark
Puoi eseguire i benchmark nello stesso modo in cui esegui i test strumentati. Puoi eseguire la funzione di test o l'intera classe con l'icona della barra laterale accanto.

Assicurati di aver selezionato un dispositivo fisico, perché l'esecuzione di benchmark sull'emulatore Android non riesce in fase di runtime con un avviso che indica che il benchmark può fornire risultati errati. Anche se tecnicamente puoi eseguirlo su un emulatore, stai misurando le prestazioni della macchina host. Se è sottoposto a un carico elevato, i benchmark vengono eseguiti più lentamente e viceversa.

Una volta eseguito il benchmark, l'app viene ricompilata e poi vengono eseguiti i benchmark. I benchmark avviano, arrestano e persino reinstallano la tua app più volte in base al iterations che definisci.
Al termine dei benchmark, puoi visualizzare i tempi nell'output di Android Studio, come mostrato nello screenshot seguente:

Dallo screenshot puoi notare che il tempo di avvio dell'app è diverso per ogni CompilationMode. I valori mediani sono mostrati nella tabella seguente:
timeToInitialDisplay [ms] | timeToFullDisplay [ms] | |
Nessuno | 202.2 | 818,8 |
BaselineProfiles | 193.7 | 637.9 |
Miglioramento | 4% | 28% |
La differenza tra le modalità di compilazione per timeToFullDisplay è di 180 ms,il che rappresenta un miglioramento di circa il 28% solo con un profilo di base. CompilationNone ha prestazioni peggiori perché il dispositivo deve eseguire la maggior parte della compilazione JIT durante l'avvio dell'app. CompilationBaselineProfiles ha prestazioni migliori perché la compilazione parziale con i profili di base AOT compila il codice che l'utente ha maggiori probabilità di utilizzare e lascia il codice non critico non precompilato, in modo che non debba essere caricato immediatamente.
10. (Facoltativo) Verifica il miglioramento delle prestazioni di scorrimento
Analogamente al passaggio precedente, puoi misurare e verificare le prestazioni di scorrimento. Innanzitutto, crea una classe di test ScrollBenchmarks con la regola di benchmark e due metodi di test che utilizzano diverse modalità di compilazione:
@LargeTest
@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {
@get:Rule
val rule = MacrobenchmarkRule()
@Test
fun scrollCompilationNone() = scroll(CompilationMode.None())
@Test
fun scrollCompilationBaselineProfiles() = scroll(CompilationMode.Partial())
private fun scroll(compilationMode: CompilationMode) {
// TODO implement
}
}
All'interno del metodo scroll, utilizza la funzione measureRepeated con i parametri richiesti. Per il parametro metrics, utilizza FrameTimingMetric, che misura il tempo necessario per produrre i frame dell'interfaccia utente:
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
// TODO implement
},
measureBlock = {
// TODO implement
}
)
}
Questa volta, devi dividere maggiormente le interazioni tra setupBlock e measureBlock per misurare solo le durate dei frame durante il primo layout e lo scorrimento dei contenuti. Pertanto, inserisci le funzioni che avviano la schermata predefinita in setupBlock e le funzioni di estensione già create waitForAsyncContent() e scrollSnackListJourney() in measureBlock:
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
pressHome()
startActivityAndWait()
},
measureBlock = {
waitForAsyncContent()
scrollSnackListJourney()
}
)
}
Una volta pronto il benchmark, puoi eseguirlo come prima per ottenere i risultati mostrati nello screenshot seguente:

FrameTimingMetric restituisce la durata dei frame in millisecondi (frameDurationCpuMs) al 50°, 90°, 95° e 99° percentile. Su Android 12 (livello API 31) e versioni successive, restituisce anche il tempo di superamento del limite dei frame (frameOverrunMs). Il valore può essere negativo, il che significa che è rimasto tempo extra per produrre il frame.
Dai risultati puoi notare che CompilationBaselineProfiles ha in media una durata del frame più breve di 2 ms, il che potrebbe non essere percepibile dagli utenti. Tuttavia, per gli altri percentili i risultati sono più evidenti. Per P99, la differenza è di 43,5 ms, ovvero più di 3 frame saltati su un dispositivo che funziona a 90 FPS. Ad esempio, per Pixel 6, 1000 ms / 90 FPS = circa 11 ms di tempo massimo per il rendering di un frame.
11. Complimenti
Congratulazioni, hai completato correttamente questo codelab e migliorato il rendimento della tua app con i profili di base.
Altre risorse
Consulta le seguenti risorse aggiuntive:
- Esamina il rendimento dell'app con Macrobenchmark: codelab che approfondisce il benchmarking.
- Esempi di rendimento: repository che contiene Macrobenchmark e altri esempi di rendimento.
- App di esempio Now In Android: un'applicazione reale che utilizza il benchmarking e i profili di base per migliorare il rendimento.