Basisprofile erstellen

Baseline-Profile sind entscheidend, um die Leistung von Jetpack Compose zu maximieren. Wenn Sie Ihre Critical User Journeys vorkompilieren, wird Ihre Compose-UI reibungslos gerendert.

Mit der Jetpack Macrobenchmark-Bibliothek und BaselineProfileRule können Sie automatisch Profile für jeden App-Release erstellen. Wir empfehlen, com.android.tools.build:gradle:8.0.0 oder höher zu verwenden, um die Build-Verbesserungen bei der Verwendung von Baseline-Profilen zu nutzen.

So erstellen Sie ein neues Baseline-Profil:

  1. Richten Sie das Baseline-Profilmodul ein.
  2. Definieren Sie den JUnit-Test, mit dem Baseline-Profile generiert werden.
  3. Fügen Sie die Critical User Journeys (CUJs) hinzu, die Sie optimieren möchten.
  4. Generieren Sie das Baseline-Profil.

Nachdem Sie das Baseline-Profil erstellt haben, führen Sie einen Benchmark-Test mit einem physischen Gerät durch, um die Geschwindigkeitsverbesserungen zu messen.

Neues Baseline-Profil mit AGP 8.2 oder höher erstellen

Am einfachsten lässt sich ein neues Baseline-Profil mit der Baseline-Profil-Modulvorlage erstellen, die ab Android Studio Iguana und Android-Gradle-Plug-in (AGP) 8.2 verfügbar ist.

Mit der Modulvorlage für den Baseline-Profilgenerator in Android Studio wird die Erstellung eines neuen Moduls zum Generieren und Benchmarken von Baseline-Profilen automatisiert. Wenn Sie die Vorlage ausführen, wird der Großteil der typischen Build-Konfiguration, der Baseline-Profilgenerierung und des Bestätigungscodes generiert. Die Vorlage erstellt Code zum Generieren und Benchmarking von Baseline-Profilen, um den App-Start zu messen.

Basisprofilmodul einrichten

So führen Sie die Vorlage für das Basisprofilmodul aus:

  1. Wählen Sie File > New > New Module aus.
  2. Wählen Sie im Bereich Vorlagen die Vorlage Baseline Profile Generator aus und konfigurieren Sie sie:
    Abbildung 1. Modulvorlage für den Baseline-Profilgenerator.
    Die Vorlage enthält die folgenden Felder:
    • Zielanwendung: die App, für die das Baseline-Profil generiert wird. Wenn Ihr Projekt nur ein einziges App-Modul enthält, gibt es in dieser Liste nur ein Element.
    • Modulname: Der Name, den Sie für das zu erstellende Baseline-Profilmodul verwenden möchten.
    • Paketname: Der gewünschte Paketname für das Basisprofilmodul.
    • Sprache: ob der generierte Code in Kotlin oder Java sein soll.
    • Build configuration language: Hier können Sie festlegen, ob Sie Kotlin Script (KTS) oder Groovy für Ihre Build-Konfigurationsskripts verwenden möchten.
    • Von Gradle verwaltetes Gerät verwenden: Gibt an, ob Sie von Gradle verwaltete Geräte zum Testen Ihrer App verwenden.
  3. Klicken Sie auf Fertigstellen, um das neue Modul zu erstellen. Wenn Sie die Versionsverwaltung verwenden, werden Sie möglicherweise aufgefordert, die neu erstellten Moduldateien der Versionsverwaltung hinzuzufügen.

Baseline-Profilgenerator definieren

Das neu erstellte Modul enthält Tests, um das Baseline-Profil zu generieren und zu benchmarken, und testet nur den grundlegenden App-Start. Wir empfehlen, diese um CUJs und erweiterte Startworkflows zu ergänzen. Achten Sie darauf, dass alle Tests im Zusammenhang mit dem App-Start in einem rule-Block enthalten sind, wobei includeInStartupProfile auf true festgelegt ist. Umgekehrt sollten Sie für eine optimale Leistung darauf achten, dass alle Tests, die nicht mit dem App-Start zusammenhängen, nicht in einem Startprofil enthalten sind. Mit Optimierungen für den App-Start wird ein spezieller Teil eines Baseline-Profils definiert, der als Startprofil bezeichnet wird.

Die Wartbarkeit wird verbessert, wenn Sie diese CUJs außerhalb des generierten Baseline-Profils und des Benchmark-Codes abstrahieren, damit sie für beide verwendet werden können. Das bedeutet, dass Änderungen an Ihren CUJs einheitlich verwendet werden.

Basisprofil generieren und installieren

Die Modulvorlage für Baseline-Profile fügt eine neue Ausführungskonfiguration hinzu, um das Baseline-Profil zu generieren. Wenn Sie Produktvarianten verwenden, erstellt Android Studio mehrere Ausführungskonfigurationen, sodass Sie für jede Variante separate Baseline-Profile generieren können.

Die Ausführungskonfiguration „Generate Baseline Profile“
Abbildung 2: Wenn Sie diese Konfiguration ausführen, wird das Baseline-Profil generiert.

Wenn die Ausführungskonfiguration Baseline-Profil generieren abgeschlossen ist, wird das generierte Baseline-Profil in die Datei src/variant/generated/baselineProfiles/baseline-prof.txt im Modul kopiert, für das ein Profil erstellt wird. Die Varianten-Optionen sind entweder der Release-Build-Typ oder eine Build-Variante, die den Release-Build-Typ umfasst.

Das generierte Baseline-Profil wird ursprünglich in build/outputs erstellt. Der vollständige Pfad wird durch die Variante oder Version der App, für die ein Profil erstellt wird, und durch die Verwendung eines von Gradle verwalteten Geräts oder eines verbundenen Geräts für die Profilerstellung bestimmt. Wenn Sie die Namen verwenden, die von den durch die Vorlage generierten Code- und Build-Konfigurationen verwendet werden, wird das Baseline-Profil in der Datei build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt erstellt. Sie müssen wahrscheinlich nicht direkt mit dieser Version des generierten Basisprofils interagieren, es sei denn, Sie kopieren es manuell in die Zielmodule (nicht empfohlen).

Neues Baseline-Profil mit AGP 8.1 erstellen

Wenn Sie die Modulvorlage für Baseline-Profile nicht verwenden können, verwenden Sie die Modulvorlage für Macrobenchmarks und das Baseline-Profil-Gradle-Plug-in, um ein neues Baseline-Profil zu erstellen. Wir empfehlen, diese Tools ab Android Studio Giraffe und AGP 8.1 zu verwenden.

So erstellen Sie ein neues Baseline-Profil mit der Macrobenchmark-Modulvorlage und dem Baseline-Profil-Gradle-Plug-in:

  1. Richten Sie in Ihrem Gradle-Projekt ein Macrobenchmark-Modul ein.
  2. Definieren Sie eine neue Klasse mit dem Namen BaselineProfileGenerator:

    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }
    

    Der Generator kann Interaktionen mit Ihrer App enthalten, die über den Start der App hinausgehen. So können Sie die Laufzeitleistung Ihrer App optimieren, z. B. beim Scrollen durch Listen, beim Ausführen von Animationen und beim Navigieren innerhalb einer Activity. Weitere Beispiele für Tests, bei denen @BaselineProfileRule zur Verbesserung von Critical User Journeys verwendet wird.

  3. Fügen Sie das Baseline-Profil-Gradle-Plug-in (libs.plugins.androidx.baselineprofile) hinzu. Mit dem Plug-in lassen sich Baseline-Profile einfacher generieren und in Zukunft verwalten.

  4. Führen Sie zum Generieren des Baseline-Profils die Gradle-Aufgaben :app:generateBaselineProfile oder :app:generateVariantBaselineProfile im Terminal aus.

    Führen Sie den Generator als Instrumentierungstest auf einem gerooteten physischen Gerät, einem Emulator oder einem von Gradle verwalteten Gerät aus. Wenn Sie ein von Gradle verwaltetes Gerät verwenden, legen Sie aosp als systemImageSource fest, da Sie Root-Zugriff für den Baseline-Profilgenerator benötigen.

    Am Ende der Erstellungsaufgabe wird das Baseline-Profil nach app/src//generated/baselineProfiles kopiert.

Neues Baseline-Profil ohne Vorlagen erstellen

Wir empfehlen, ein Baseline-Profil mit der Baseline-Profil-Modulvorlage (bevorzugt) oder der Macrobenchmark-Vorlage von Android Studio zu erstellen. Sie können aber auch das Baseline-Profil-Gradle-Plug-in allein verwenden. Weitere Informationen zum Gradle-Plug-in für Basisprofile finden Sie unter Generierung von Basisprofilen konfigurieren.

So erstellen Sie ein Baseline-Profil direkt mit dem Baseline-Profil-Gradle-Plug-in:

  1. Erstellen Sie ein neues com.android.test-Modul, z. B. :baseline-profile.
  2. Konfigurieren Sie die Datei build.gradle.kts für :baseline-profile:

    1. Wenden Sie das Plug-in androidx.baselineprofile an.
    2. Achten Sie darauf, dass targetProjectPath auf das Modul :app verweist.
    3. Optional können Sie ein von Gradle verwaltetes Gerät (GMD) hinzufügen. In diesem Beispiel ist das pixel6Api31. Wenn keine Angabe erfolgt, verwendet das Plug-in ein verbundenes Gerät, entweder emuliert oder physisch.
    4. Wenden Sie die gewünschte Konfiguration an, wie im folgenden Beispiel gezeigt.

    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. Erstellen Sie im Testmodul :baseline-profile einen Baseline-Profiltest. Das folgende Beispiel ist ein Test, bei dem ein Baseline-Profil für den App-Start generiert wird.

        class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                uiAutomator { startApp(PACKAGE_NAME) }
            }
        )
    }
    
  4. Aktualisieren Sie die Datei build.gradle.kts im App-Modul, z. B. :app.

    1. Wenden Sie das Plug-in androidx.baselineprofile an.
    2. Fügen Sie dem :baseline-profile-Modul eine baselineProfile-Abhängigkeit hinzu.

    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. Generieren Sie das Profil, indem Sie die Gradle-Aufgaben :app:generateBaselineProfile oder :app:generateVariantBaselineProfile ausführen.

  6. Am Ende der Generierungsaufgabe wird das Baseline-Profil nach app/src/variant/generated/baselineProfiles kopiert.

Benchmark für das Baseline-Profil erstellen

Wenn Sie Ihr Baseline-Profil benchmarken möchten, erstellen Sie eine neue Konfiguration für die Ausführung von instrumentierten Android-Tests über die Aktion im Gutter, die die in der Datei StartupBenchmarks.kt definierten Benchmarks ausführt. Weitere Informationen zu Benchmarktests finden Sie unter Macrobenchmark-Klasse erstellen und Baseline-Profile mit der Macrobenchmark-Bibliothek benchmarken.

Abbildung 3: Android-Tests über die Aktion in der Leiste ausführen

Wenn Sie dies in Android Studio ausführen, enthält die Build-Ausgabe Details zu den Geschwindigkeitsverbesserungen, die das Baseline-Profil bietet:

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

Alle erforderlichen Codepfade erfassen

Die beiden wichtigsten Messwerte für die Startzeit von Apps sind:

Die TTFD wird gemeldet, sobald die Methode reportFullyDrawn des ComponentActivity aufgerufen wird. Wenn reportFullyDrawn nie aufgerufen wird, wird stattdessen die TTID gemeldet. Möglicherweise müssen Sie den Aufruf von reportFullyDrawn verzögern, bis das asynchrone Laden abgeschlossen ist. Wenn die Benutzeroberfläche beispielsweise eine dynamische Lazy List enthält, wird die Liste möglicherweise durch eine Hintergrundaufgabe gefüllt, die abgeschlossen wird, nachdem die Liste zum ersten Mal gezeichnet wurde und somit nachdem die Benutzeroberfläche als vollständig gezeichnet markiert wurde. In solchen Fällen wird Code, der ausgeführt wird, nachdem die Benutzeroberfläche vollständig dargestellt wurde, nicht in das Baseline-Profil aufgenommen.

Wenn Sie die Listenpopulation in Ihr Baseline-Profil aufnehmen möchten, rufen Sie die FullyDrawnReporter mit getFullyDrawnReporter ab und fügen Sie ihr im App-Code einen Reporter hinzu. Geben Sie den Reporter frei, sobald die Hintergrundaufgabe die Liste gefüllt hat. Der FullyDrawnReporter ruft die Methode reportFullyDrawn erst auf, wenn alle Reporter freigegeben wurden. Dadurch enthält das Baseline-Profil die Codepfade, die zum Ausfüllen der Liste erforderlich sind. Dadurch ändert sich das Verhalten der App für den Nutzer nicht, aber das Baseline-Profil kann alle erforderlichen Codepfade enthalten.

Verwenden Sie die folgenden Compose APIs, um den vollständig gezeichneten Zustand anzugeben:

  • ReportDrawn gibt an, dass Ihre komponierbare Funktion sofort für die Interaktion bereit ist.
  • ReportDrawnWhen verwendet ein Prädikat wie list.count > 0, um anzugeben, wann Ihre komponierbare Funktion für die Interaktion bereit ist.
  • ReportDrawnAfter verwendet eine suspendierende Methode, die nach Abschluss angibt, dass Ihre komponierbare Funktion für die Interaktion bereit ist.