Scrivi un Macrobenchmark

Usa la libreria Macrobenchmark per testare casi d'uso più ampi della tua app, tra cui l'avvio dell'app e complesse manipolazioni dell'interfaccia utente, come lo scorrimento di una RecyclerView o l'esecuzione di animazioni. Se vuoi testare aree più piccole del codice, consulta la libreria di Microbenchmark. Questa pagina mostra come configurare la libreria Macrobenchmark.

La libreria genera risultati di benchmarking sia nella console di Android Studio sia in un file JSON con maggiori dettagli. Fornisce anche 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 riferimento. Innanzitutto, imposta la libreria Macrobenchmark, quindi puoi creare un profilo di riferimento.

Configurazione del progetto

Ti consigliamo di utilizzare Macrobenchmark con la versione più recente di Android Studio per le funzionalità dell'IDE che si integrano con Macrobenchmark.

Configura il modulo Macrobenchmark

I Macrobenchmarks 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 progetto per misurare l'app creata da un modulo dell'app, incluso un esempio di benchmark per le startup.

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

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

  2. Seleziona Benchmark dal riquadro Modelli. Puoi personalizzare l'app di destinazione, ovvero l'app da sottoporre a benchmark, 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 benchmark di un'app, nota come target di Macrobenchmark, deve essere profileable, che consente di leggere informazioni di traccia dettagliate senza influire sulle prestazioni. La procedura guidata di inserimento dei moduli 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 di Macrobenchmark per abilitare l'acquisizione del profilo, nonché la reimpostazione e la cancellazione della cache dello Shader.

Configura l'app di cui è stato eseguito il benchmark il più vicino possibile alla versione di release o di produzione. Configuralo come non eseguibile del debug e preferibilmente con la minimizzazione attivata, per migliorare le prestazioni. In genere, per farlo devi creare una copia della variante della release, che ha le stesse prestazioni, 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 verifichi la variante corretta della tua app, come mostrato nella Figura 2:

  1. Eseguire una sincronizzazione Gradle.
  2. Apri il riquadro Crea varianti.
  3. Seleziona la variante di benchmark sia dell'app sia del modulo Macrobenchmark.

Seleziona variante di benchmark

Figura 2. Seleziona la variante del benchmark.

(Facoltativo) Configurare un'app per più moduli

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. Gli altri moduli Gradle possono 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 questo segnale, il tipo di build benchmark appena aggiunto provoca l'errore della build e restituisce 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 progetto, scegli benchmark per i moduli :app e :macrobenchmark e release per tutti gli altri moduli presenti nella tua app, come mostrato nella Figura 3:

Confronta le varianti per un progetto multi-modulo con i tipi di build di release e benchmark selezionati

Figura 3. Esegui il benchmark delle varianti per il progetto multi-modulo con i tipi di build di release e benchmark selezionati.

Per saperne di più, consulta Utilizzare la gestione delle dipendenze sensibile alle varianti.

(Facoltativo) Configurare i sapori dei prodotti

Se nella tua app hai impostato più versioni di prodotto, configura il modulo :macrobenchmark in modo che sappia quale versione della tua app creare e confrontare.

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

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 compilazione simile a quello 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 spiegano come configurare il benchmarking con più versioni di prodotti.

Utilizza strategiaDimensione mancante

Se specifichi missingDimensionStrategy nel campo defaultConfig del modulo :macrobenchmark, il sistema di compilazione deve ricorrere alla dimensione flavor. Specifica quali dimensioni utilizzare se non le trovi nel modulo. Nell'esempio seguente, la versione 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 benchmark solo per la versione di prodotto specificata, il che è utile se sai che solo una versione di prodotto ha la configurazione adeguata per il benchmark.

Definisci i gusti di prodotto nel modulo :macrobenchmark

Se vuoi creare e confrontare le versioni di altri prodotti, definisci queste versioni nel modulo :macrobenchmark. Specificalo in modo simile nel modulo :app, ma assegna solo productFlavors 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 Crea varianti, come mostrato nella Figura 4:

Confronta le varianti per il progetto con versioni di prodotto che mostrano
productionBenchmark e release selezionata

Figura 4. Confronta le varianti del progetto con le versioni di prodotto che mostrano "productionBenchmark" e "release" selezionata.

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

Crea una classe macrobenchmark

I test di benchmark sono forniti 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 specificare almeno il packageName dell'app target, gli elementi metrics che vuoi misurare e il numero di iterations che deve essere eseguito dal 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 relative alla 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 nello stesso modo in cui esegui qualsiasi altro @Test utilizzando l'azione grondaia accanto alla classe o al metodo di test, come mostrato nella Figura 5.

Esegui macrobenchmark con azione gutter accanto alla classe di test

Figura 5. Esegui Macrobenchmark con l'azione gutter 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 questo comando:

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

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

Risultati benchmark

Al termine dell'esecuzione del benchmark, le metriche vengono visualizzate direttamente in Android Studio e inviate in un file JSON per l'utilizzo di CI. Ogni iterazione misurata acquisisce una traccia di sistema separata. Puoi aprire i risultati di queste tracce facendo clic sui link nel riquadro Risultati del test, come mostrato nella Figura 6:

Risultati di avvio
di Macrobenchmark

Figura 6. Risultati di avvio di Macrobenchmark.

Una volta caricata la traccia, 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
della traccia di Studio

Figura 7. Selezione del processo di traccia di Studio.

Una volta caricato il file di traccia, Studio mostra i risultati nello strumento Profiler CPU:

Studio
Trace

Figura 8. Traccia di Studio.

Anche i report JSON e le eventuali tracce di profilazione vengono copiati automaticamente dal dispositivo all'host. Questi valori sono scritti sulla macchina 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 usare lo strumento Perfetto per analizzare un file di traccia, devi eseguire ulteriori passaggi. Perfetto ti permette di controllare tutti i processi che avvengono sul dispositivo durante la traccia, mentre il profiler della CPU di Android Studio limita l'ispezione a un singolo processo.

Se richiami i test da Android Studio o dalla riga di comando di Gradle, i file di traccia vengono copiati automaticamente dal dispositivo all'host. che sono scritti sulla macchina host nella seguente posizione:

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

Una volta presente il file di traccia nel sistema host, puoi aprirlo in Android Studio selezionando File > Apri nel menu. Questa mostra la visualizzazione dello strumento Profiler nella sezione precedente.

Errori di configurazione

Se l'app non è configurata correttamente (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 in esaurimento, il che potrebbe compromettere la disponibilità del core e la velocità di clock.

Personalizza i benchmark

La funzione measureRepeated accetta vari parametri che influenzano le metriche raccolte dalla libreria, il modo in cui l'app viene avviata e compilata o il numero di iterazioni eseguite dal benchmark.

Acquisisci le metriche

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

Per ulteriori informazioni sulle metriche, consulta Acquisizione delle metriche di Macrobenchmark.

Migliora i dati di traccia con eventi personalizzati

Può essere utile instrumentare l'app con eventi di traccia personalizzati, che sono disponibili insieme al resto del report sulle tracce e possono aiutarti a segnalare problemi specifici della tua app. Per scoprire di più sulla creazione di eventi di traccia personalizzati, consulta Definire eventi di traccia personalizzati.

Modalità Compilation

Macrobenchmarks può specificare un CompilationMode, che definisce la quantità di app che deve essere precompilata dal bytecode DEX (il formato bytecode all'interno di un APK) al codice macchina (simile al C++ precompilato).

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

Puoi installare un profilo di riferimento se l'app target contiene sia un profilo di riferimento sia la libreria ProfileInstaller.

Su Android 7 e versioni successive, puoi personalizzare CompilationMode in base alla quantità di precompilazione sul dispositivo in modo da imitare diversi livelli di compilazione in anticipo (AOT) o memorizzazione nella cache di JIT. Vedi CompilationMode.Full, CompilationMode.Partial, CompilationMode.None e CompilationMode.Ignore.

Questa funzionalità è basata sui comandi di compilazione ART. Ogni benchmark cancella i dati del profilo prima di iniziare, per garantire l'assenza di interferenze tra i benchmark.

Modalità Avvio

Per avviare un'attività, puoi passare una modalità di avvio predefinita: COLD, WARM o HOT. Questo parametro modifica il modo in cui viene avviata l'attività e lo stato del processo all'inizio del test.

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

Campioni

Un progetto di esempio è disponibile nel Esempio di Macrobenchmark del repository su GitHub.

Fornisci feedback

Per segnalare problemi o inviare richieste di funzionalità per Jetpack Macrobenchmark, consulta il tracker pubblico dei problemi.