Scrivi un Macrobenchmark

Utilizza la libreria Macrobenchmark per testare casi d'uso più ampi della tua app, inclusi l'avvio dell'app e manipolazioni complesse della UI, come lo scorrimento di un RecyclerView o l'esecuzione di animazioni. Se vuoi testare aree più piccole del tuo codice, consulta la libreria Microbenchmark. Questa pagina mostra come configurare la libreria Macrobenchmark.

La libreria restituisce i risultati del benchmarking sia alla console di Android Studio sia a un file JSON con maggiori dettagli. Fornisce inoltre file di traccia che puoi caricare e analizzare in Android Studio.

Utilizza la libreria Macrobenchmark in un ambiente di integrazione continua (CI), come descritto in Benchmark nell'integrazione continua.

Puoi utilizzare Macrobenchmark per generare profili di base. Innanzitutto, configura la libreria Macrobenchmark, poi potrai creare un profilo di base.

Configurazione del progetto

Ti consigliamo di utilizzare Macrobenchmark con l'ultima versione di Android Studio per le funzionalità dell'IDE che si integrano con Macrobenchmark.

Configurare il modulo Macrobenchmark

I macrobenchmark richiedono un modulo com.android.test separato dal codice dell'app, responsabile dell'esecuzione dei test che misurano la tua app.

In Android Studio è disponibile un modello per semplificare la configurazione del modulo Macrobenchmark. Il modello di modulo di benchmarking crea automaticamente un modulo nel tuo progetto per misurare l'app creata da un modulo dell'app, incluso un benchmark di avvio di esempio.

Per utilizzare il modello di modulo per creare un nuovo modulo:

  1. Fai clic con il tasto destro del mouse sul progetto o sul modulo nel riquadro Progetto di Android Studio e seleziona Nuovo > Modulo.

  2. Seleziona Benchmark dal riquadro Modelli. Puoi personalizzare l'app di destinazione, ovvero l'app da confrontare, nonché il nome del pacchetto e del modulo per il nuovo modulo Macrobenchmark.

  3. Fai clic su Fine.

Modello del modulo
benchmark

Figura 1. Modello del modulo Benchmark.

Configurare l'app

Per eseguire il benchmarking di un'app, nota come target di Macrobenchmark, l'app deve essere profileable, il che consente di leggere informazioni dettagliate sulla traccia senza influire sul rendimento. La procedura guidata del modulo aggiunge automaticamente il tag <profileable> al file AndroidManifest.xml dell'app.

Assicurati che l'app di destinazione includa ProfilerInstaller 1.3 o versioni successive, necessarie alla libreria Macrobenchmark per attivare l'acquisizione del profilo e la reimpostazione e la cancellazione della cache degli shader.

Configura l'app di riferimento il più vicino possibile alla versione di release o di produzione. Configuralo come non eseguibile in modalità di debug e, preferibilmente, con la minimizzazione attiva, in modo da migliorare il rendimento. In genere, questa operazione viene eseguita creando una copia della variante di rilascio, che esegue la stessa operazione, ma viene firmata localmente con chiavi di debug. In alternativa, puoi utilizzare initWith per indicare a Gradle di farlo per te:

Kotlin

buildTypes {
    getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
    }

    create("benchmark") {
        initWith(getByName("release"))
        signingConfig = signingConfigs.getByName("debug")
    }
}

Trendy

buildTypes {
    getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
        )
        // In real app, this would use its own release keystore
        signingConfig = signingConfigs.getByName("debug")
    }
}

Per assicurarti che l'esecuzione del benchmark crei e testi la variante corretta della tua app, come mostrato nella figura 2, procedi nel seguente modo:

  1. Esegui una sincronizzazione Gradle.
  2. Apri il riquadro Varianti di build.
  3. Seleziona la variante di benchmark sia dell'app sia del modulo Macrobenchmark.

Seleziona la variante
del benchmark

Figura 2. Seleziona la variante di benchmark.

(Facoltativo) Configurare l'app multimodulo

Se la tua app ha più di un modulo Gradle, assicurati che gli script di build sappiano quale variante di build compilare. Aggiungi la proprietàmatchingFallbacks al tipo di build benchmark dei moduli :macrobenchmark e :app. Il resto dei moduli Gradle può avere la stessa configurazione di prima.

Kotlin

create("benchmark") {
    initWith(getByName("release"))
    signingConfig = signingConfigs.getByName("debug")

    matchingFallbacks += listOf("release")
 }

Trendy

benchmark {
    initWith buildTypes.release
    signingConfig signingConfigs.debug

    matchingFallbacks = ['release']
 }

Senza questa impostazione, il tipo di build benchmark appena aggiunto causa l'errore della build e fornisce il seguente messaggio di errore:

> Could not resolve project :shared.
     Required by:
         project :app
      > No matching variant of project :shared was found.
      ...

Quando selezioni le varianti di build nel tuo progetto, scegli benchmark per i moduli :app e :macrobenchmark e release per tutti gli altri moduli che hai nella tua app, come mostrato nella figura 3:

Varianti di benchmark per il progetto multimodulo con i tipi di build di rilascio e benchmark selezionati

Figura 3. Varianti di benchmark per il progetto multimodulo con i tipi di build di rilascio e benchmark selezionati.

Per ulteriori informazioni, consulta Utilizzare la gestione delle dipendenze in base alle varianti.

(Facoltativo) Configurare le varianti di prodotto

Se nella tua app sono impostate più varianti di prodotto, configura il modulo :macrobenchmark in modo che sappia quale variante di prodotto della tua app creare e confrontare.

Gli esempi in questa pagina utilizzano le due varianti del prodotto nel modulo :app: demo e production, come mostrato nel seguente snippet:

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
        // ...
    }
    create("production") {
        dimension = "environment"
        // ...
    }
}

Trendy

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
        // ...
    }

    production {
        dimension 'environment'
        // ...
    }
}

Senza questa configurazione, potresti ricevere un errore di build simile a quello che si verifica con più moduli Gradle:

Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
   > Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
      > Could not resolve project :app.
        Required by:
            project :macrobenchmark
         > The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
             -   demoBenchmarkRuntimeElements
             -   productionBenchmarkRuntimeElements
           All of them match the consumer attributes:
           ...

Le due sezioni seguenti descrivono i modi per configurare il benchmarking con più varianti di prodotto.

Utilizza missingDimensionStrategy

Se specifichi missingDimensionStrategy in defaultConfig del modulo :macrobenchmark, il sistema di build torna alla dimensione della variante. Specifica le dimensioni da utilizzare se non le trovi nel modulo. Nell'esempio seguente, la variante production viene utilizzata come dimensione predefinita:

Kotlin

defaultConfig {
    missingDimensionStrategy("environment", "production")
}

Trendy

defaultConfig {
    missingDimensionStrategy "environment", "production"
}

In questo modo, il modulo :macrobenchmark è in grado di creare e valutare solo la variante del prodotto specificata, il che è utile se sai che solo una variante del prodotto ha la configurazione corretta per essere valutata.

Definisci le varianti del prodotto nel modulo :macrobenchmark

Se vuoi creare e confrontare altri gusti del prodotto, definiscili nel modulo :macrobenchmark. Specificalo in modo simile a quanto fatto nel modulo :app, ma assegna productFlavors solo a un dimension. Non sono necessarie altre impostazioni:

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
    }
    create("production") {
        dimension = "environment"
    }
}

Trendy

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
    }

    production {
        dimension 'environment'
    }
}

Dopo aver definito e sincronizzato il progetto, scegli la variante di build pertinente dal riquadro Varianti di build, come mostrato nella figura 4:

Varianti di benchmark per il progetto con le varianti del prodotto che mostrano
productionBenchmark e release
selezionati

Figura 4. Varianti benchmark per il progetto con le varianti di prodotto che mostrano "productionBenchmark" e "release" selezionati.

Per saperne di più, vedi Risolvere gli errori di build relativi alla corrispondenza delle varianti.

Crea una classe di macrobenchmark

Il test di benchmarking viene fornito tramite l'API della regola JUnit4 MacrobenchmarkRule nella libreria Macrobenchmark. Contiene un metodo measureRepeated che consente di specificare varie condizioni su come eseguire e confrontare l'app di destinazione.

Devi almeno specificare il packageName dell'app di destinazione, quali metrics vuoi misurare e per quante iterations deve essere eseguito il benchmark.

Kotlin

@LargeTest
@RunWith(AndroidJUnit4::class)
class SampleStartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun startup() = benchmarkRule.measureRepeated(
        packageName = TARGET_PACKAGE,
        metrics = listOf(StartupTimingMetric()),
        iterations = DEFAULT_ITERATIONS,
        setupBlock = {
            // Press home button before each run to ensure the starting activity isn't visible.
            pressHome()
        }
    ) {
        // starts default launch activity
        startActivityAndWait()
    }
}

Java

@LargeTest
@RunWith(AndroidJUnit4.class)
public class SampleStartupBenchmark {
    @Rule
    public MacrobenchmarkRule benchmarkRule = new MacrobenchmarkRule();

    @Test
    public void startup() {
        benchmarkRule.measureRepeated(
            /* packageName */ TARGET_PACKAGE,
            /* metrics */ Arrays.asList(new StartupTimingMetric()),
            /* iterations */ 5,
            /* measureBlock */ scope -> {
                // starts default launch activity
                scope.startActivityAndWait();
                return Unit.INSTANCE;
            }
        );
    }
}

Per tutte le opzioni di personalizzazione del benchmark, consulta la sezione Personalizzare i benchmark.

Esegui il benchmark

Esegui il test da Android Studio per misurare le prestazioni della tua app sul tuo dispositivo. Puoi eseguire i benchmark allo stesso modo in cui esegui qualsiasi altro @Test utilizzando l'azione di gutter accanto alla classe o al metodo di test, come mostrato nella figura 5.

Esegui macrobenchmark con l&#39;azione di grondaia accanto alla classe di test

Figura 5. Esegui Macrobenchmark con l'azione di grondaia accanto alla classe di test.

Puoi anche eseguire tutti i benchmark in un modulo Gradle dalla riga di comando eseguendo il comando connectedCheck:

./gradlew :macrobenchmark:connectedCheck

Puoi eseguire un singolo test eseguendo il seguente comando:

./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup

Consulta la sezione Benchmark nell'integrazione continua per informazioni su come eseguire e monitorare i benchmark nell'integrazione continua.

Risultati benchmark

Dopo l'esecuzione di un benchmark riuscita, le metriche vengono visualizzate direttamente in Android Studio e vengono generate per l'utilizzo di CI in un file JSON. Ogni iterazione misurata acquisisce una traccia di sistema separata. Puoi aprire questi risultati della traccia facendo clic sui link nel riquadro Risultati test, come mostrato nella figura 6:

Risultati dell&#39;avvio del macrobenchmark

Figura 6. Risultati dell'avvio di macrobenchmark.

Quando la traccia viene caricata, Android Studio ti chiede di selezionare il processo da analizzare. La selezione viene precompilata con il processo dell'app di destinazione, come mostrato nella figura 7:

Selezione del processo di traccia di Studio

Figura 7. Selezione del processo di tracciamento di Studio.

Dopo il caricamento del file di traccia, Studio mostra i risultati nello strumento CPU Profiler:

Studio
Trace

Figura 8. Traccia di Studio.

Anche i report JSON e le tracce di profilazione vengono copiati automaticamente dal dispositivo all'host. Questi vengono scritti sul computer host nella seguente posizione:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

Accedere manualmente ai file di traccia

Se vuoi utilizzare lo strumento Perfetto per analizzare un file di traccia, sono necessari passaggi aggiuntivi. Perfetto ti consente di ispezionare tutti i processi in esecuzione sul dispositivo durante la traccia, mentre il Profiler CPU di Android Studio limita l'ispezione a un singolo processo.

Se richiami i test da Android Studio o dalla riga di comando Gradle, i file di traccia vengono copiati automaticamente dal dispositivo all'host. Questi vengono scritti sul computer host nel seguente percorso:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace

Quando hai il file di traccia nel sistema host, puoi aprirlo in Android Studio con File > Apri nel menu. Mostra la visualizzazione dello strumento Profiler mostrata nella sezione precedente.

Errori di configurazione

Se l'app è configurata in modo errato (debug o non profilabile), Macrobenchmark restituisce un errore anziché segnalare una misurazione errata o incompleta. Puoi eliminare questi errori con l'argomento androidx.benchmark.suppressErrors.

Macrobenchmark restituisce errori anche quando tenta di misurare un emulatore o su un dispositivo con batteria scarica, il che potrebbe compromettere la disponibilità del core e la velocità di clock.

Personalizzare i benchmark

La funzione measureRepeated accetta vari parametri che influiscono sulle metriche raccolte dalla libreria, su come viene avviata e compilata l'app o su quante iterazioni vengono eseguite dal benchmark.

Acquisire le metriche

Le metriche sono il tipo principale di informazioni estratte dai benchmark. Sono disponibili le seguenti metriche:

Per ulteriori informazioni sulle metriche, consulta Acquisire le metriche Macrobenchmark.

Migliorare i dati di traccia con eventi personalizzati

Può essere utile instrumentare l'app con eventi di traccia personalizzati, che vengono visualizzati con il resto del report di traccia e possono aiutare a evidenziare problemi specifici della tua app. Per saperne di più sulla creazione di eventi di traccia personalizzati, consulta Definire eventi personalizzati.

CompilationMode

I macrobenchmark possono specificare un CompilationMode, che definisce la quantità di app da precompilare dal bytecode DEX (il formato del bytecode all'interno di un APK) al codice macchina (simile a C++ precompilato).

Per impostazione predefinita, Macrobenchmark viene eseguito con CompilationMode.DEFAULT, che installa un profilo di base, se disponibile, su Android 7 (livello API 24) e versioni successive. Se utilizzi Android 6 (livello API 23) o versioni precedenti, la modalità di compilazione compila completamente l'APK come comportamento predefinito del sistema.

Puoi installare un profilo di base se l'app di destinazione contiene sia un profilo di base sia la libreria ProfileInstaller.

Su Android 7 e versioni successive, puoi personalizzare CompilationMode per influire sulla quantità di precompilazione sul dispositivo per simulare diversi livelli di compilazione ahead-of-time (AOT) o memorizzazione nella cache JIT. Consulta CompilationMode.Full, CompilationMode.Partial, CompilationMode.None e CompilationMode.Ignore.

Questa funzionalità si basa sui comandi di compilazione ART. Ogni benchmark cancella i dati del profilo prima di iniziare, per garantire la non interferenza tra i benchmark.

StartupMode

Per eseguire l'avvio di un'attività, puoi passare una modalità di avvio predefinita: COLD, WARM o HOT. Questo parametro modifica la modalità di avvio dell'attività e lo stato del processo all'inizio del test.

Per scoprire di più sui tipi di avvio, consulta Tempo di avvio dell'app.

Campioni

Un progetto di esempio è disponibile in Macrobenchmark Sample del repository su GitHub.

Fornisci feedback

Per segnalare problemi o inviare richieste di funzionalità per Jetpack Macrobenchmark, consulta l'Issue Tracker pubblico.