1. Hinweis
In diesem Codelab erfahren Sie, wie Sie Baseline-Profile generieren, um die Leistung Ihrer Anwendung zu optimieren, und wie Sie die Leistungsvorteile der Verwendung von Baseline-Profilen überprüfen.
Voraussetzungen
- Android Studio Hedgehog (2023.1.1) oder höher
- Android-Gradle-Plug-in 8.0 oder höher
- Grundlegende Kenntnisse von Jetpack Macrobenchmark
- Ein physisches Android-Gerät mit Android 7 (API-Level 24) oder höher
Aufgaben
- Richten Sie das Projekt für die Verwendung von Baseline-Profil-Generatoren ein.
- Mit Android Studio und Jetpack Macrobenchmark können Sie Baseline-Profile generieren, um die Start- und Scrollleistung von Apps zu optimieren.
- Leistungssteigerungen mit der Jetpack Macrobenchmark-Bibliothek überprüfen
Lerninhalte
- Baseline-Profile und wie sie die Leistung der App verbessern können.
- So generieren Sie Baseline-Profile.
- Leistungssteigerungen durch Baseline-Profile.
2. Einrichtung
Klonen Sie das GitHub-Repository über die Befehlszeile mit dem folgenden Befehl:
$ git clone https://github.com/android/codelab-android-performance.git
Alternativ können Sie zwei ZIP-Dateien herunterladen:
Projekt in Android Studio öffnen
- Wählen Sie im Fenster „Willkommen bei Android Studio“
Vorhandenes Projekt öffnen aus. - Wählen Sie den Ordner
[Download Location]/codelab-android-performance/baseline-profilesaus. Achten Sie darauf, dass Sie das Verzeichnisbaseline-profilesauswählen. - Wenn Android Studio das Projekt importiert, müssen Sie das Modul
appausführen können, um die Beispielanwendung zu erstellen, mit der Sie später arbeiten.
Die Beispiel-App
In diesem Codelab arbeiten Sie mit der JetSnack-Beispielanwendung. Es handelt sich um eine virtuelle App zum Bestellen von Snacks, die Jetpack Compose verwendet.
Um die Leistung der Anwendung zu messen, müssen Sie die Struktur der Benutzeroberfläche und das Verhalten der App kennen, damit Sie über die Benchmarks auf die UI-Elemente zugreifen können. Führen Sie die App aus und machen Sie sich mit den grundlegenden Bildschirmen vertraut, indem Sie Snacks bestellen. Sie müssen nicht wissen, wie die App aufgebaut ist.

3. Was sind Baseline-Profile?
Baseline-Profile verbessern die Ausführungsgeschwindigkeit von Code ab dem ersten Start um etwa 30 %, da die Schritte zur Interpretation und Just-in-time (JIT)-Kompilierung für die enthaltenen Codepfade vermieden werden. Wenn ein Baseline-Profil in einer App oder Bibliothek enthalten ist, kann Android Runtime (ART) bestimmte Codepfade durch Ahead-of-Time (AOT)-Kompilierung optimieren. So wird die Leistung für jeden neuen Nutzer und bei jedem App-Update verbessert. Mit dieser profilgestützten Optimierung (Profile Guided Optimization, PGO) können Apps ab dem ersten Start optimiert werden, die Interaktionsverzögerung kann reduziert und die allgemeine Laufzeitleistung für Endnutzer verbessert werden.
Mit einem Baseline-Profil werden alle Nutzerinteraktionen wie App-Start, Navigation zwischen Bildschirmen oder Scrollen durch Inhalte ab der ersten Ausführung reibungsloser. Durch die Erhöhung der Geschwindigkeit und Reaktionsfähigkeit einer App können Sie die Anzahl der aktiven Nutzer pro Tag und die durchschnittliche Rückkehrrate steigern.
Baseline-Profile helfen, die Optimierung über den App-Start hinaus zu lenken, indem sie gängige Nutzerinteraktionen bereitstellen, die die App-Laufzeit ab dem ersten Start verbessern. Die geführte AOT-Kompilierung ist nicht von Nutzergeräten abhängig und kann einmal pro Release auf einem Entwicklungscomputer anstelle eines Mobilgeräts durchgeführt werden. Wenn Releases mit einem Baseline-Profil ausgeliefert werden, sind App-Optimierungen viel schneller verfügbar als bei der Verwendung von Cloud-Profilen allein.
Wenn kein Baseline-Profil verwendet wird, wird der gesamte App-Code entweder nach der Interpretation im Arbeitsspeicher JIT-kompiliert oder im Hintergrund in eine odex-Datei geschrieben, wenn das Gerät im Leerlauf ist. Nutzer haben dann möglicherweise eine suboptimale Erfahrung, wenn sie eine App nach der Installation oder Aktualisierung zum ersten Mal ausführen, bevor die neuen Pfade optimiert sind.
4. Modul „Baseline Profile Generator“ einrichten
Sie können Baseline-Profile mit einer Instrumentationstestklasse generieren, für die Ihrem Projekt ein neues Gradle-Modul hinzugefügt werden muss. Am einfachsten fügen Sie es Ihrem Projekt mit dem Android Studio-Modulassistenten hinzu, der in Android Studio Hedgehog oder höher enthalten ist.
Öffnen Sie das Fenster des Assistenten für neue Module, indem Sie im Bereich Project mit der rechten Maustaste auf Ihr Projekt oder Modul klicken und New > Module auswählen.

Wählen Sie im geöffneten Fenster im Bereich „Vorlagen“ die Option Baseline Profile Generator (Generator für Baseline-Profile) aus.

Neben den üblichen Parametern wie Modulname, Paketname, Sprache oder Sprache der Build-Konfiguration gibt es zwei Eingaben, die für ein neues Modul nicht üblich sind: Target application (Zielanwendung) und Use Gradle Managed Device (Von Gradle verwaltetes Gerät verwenden).
Die Zielanwendung ist das App-Modul, das zum Generieren von Baseline-Profilen verwendet wird. Wenn Sie mehrere App-Module in Ihrem Projekt haben, wählen Sie das Modul aus, für das Sie die Generatoren ausführen möchten.
Mit dem Kästchen Gradle-verwaltetes Gerät verwenden wird das Modul so festgelegt, dass die Baseline-Profil-Generatoren auf automatisch verwalteten Android-Emulatoren ausgeführt werden. Weitere Informationen zu von Gradle verwalteten Geräten finden Sie unter Tests mit von Gradle verwalteten Geräten skalieren. Wenn Sie das Häkchen entfernen, verwenden die Generatoren alle verbundenen Geräte.
Wenn Sie alle Details zum neuen Modul festgelegt haben, klicken Sie auf Fertigstellen, um mit der Modulerstellung fortzufahren.
Vom Modulassistenten vorgenommene Änderungen
Der Modul-Assistent nimmt mehrere Änderungen an Ihrem Projekt vor.
Dadurch wird ein Gradle-Modul mit dem Namen baselineprofile oder dem Namen, den Sie im Assistenten auswählen, hinzugefügt.
In diesem Modul wird das com.android.test-Plug-in verwendet, das Gradle anweist, es nicht in Ihre Anwendung aufzunehmen. Es kann also nur Testcode oder Benchmarks enthalten. Außerdem wird das androidx.baselineprofile-Plug-in angewendet, mit dem sich Baseline-Profile automatisch generieren lassen.
Der Assistent nimmt auch Änderungen am ausgewählten Zielanwendungsmodul vor. Konkret wird das androidx.baselineprofile-Plug-in angewendet, die androidx.profileinstaller-Abhängigkeit hinzugefügt und die baselineProfile-Abhängigkeit dem neu erstellten Modul build.gradle(.kts) hinzugefügt:
plugins {
id("androidx.baselineprofile")
}
dependencies {
// ...
implementation("androidx.profileinstaller:profileinstaller:1.3.0")
"baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}
Wenn Sie die androidx.profileinstaller-Abhängigkeit hinzufügen, haben Sie folgende Möglichkeiten:
- Prüfen Sie lokal, ob die generierten Baseline-Profile zu Leistungssteigerungen führen.
- Verwenden Sie Baseline Profiles unter Android 7 (API-Level 24) und Android 8 (API-Level 26), die keine Cloud-Profile unterstützen.
- Baseline-Profile auf Geräten ohne Google Play-Dienste verwenden
Mit der Abhängigkeit baselineProfile(project(":baselineprofile")) wird Gradle mitgeteilt, aus welchem Modul die generierten Baseline-Profile stammen müssen.
Nachdem Sie das Projekt festgelegt haben, schreiben Sie eine Generator-Klasse für Baseline-Profile.
5. Baseline-Profil-Generator schreiben
Normalerweise erstellen Sie Baseline-Profile für die typischen Nutzerpfade Ihrer App.
Der Modulassistent erstellt eine einfache BaselineProfileGenerator-Testklasse, mit der das Baseline-Profil für den App-Start generiert werden kann. Sie sieht so aus:
@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
}
}
}
Diese Klasse verwendet eine BaselineProfileRule-Testregel und enthält eine Testmethode zum Generieren des Profils. Der Einstiegspunkt zum Generieren des Profils ist die Funktion collect(). Dafür sind nur zwei Parameter erforderlich:
packageName: Das Paket Ihrer App.profileBlock: der letzte Lambda-Parameter.
Im profileBlock-Lambda geben Sie die Interaktionen an, die die typischen Nutzeraktionen Ihrer App abdecken. Die Bibliothek führt das profileBlock mehrmals aus, erfasst die aufgerufenen Klassen und Funktionen und generiert das Baseline-Profil auf dem Gerät mit dem zu optimierenden Code.
Standardmäßig enthält die erstellte Generator-Klasse Interaktionen zum Starten Ihrer Standard-Activity und wartet, bis der erste Frame Ihrer App mit der Methode startActivityAndWait() gerendert wird.
Generator mit benutzerdefinierten Abläufen erweitern
Die generierte Klasse enthält auch einige TODO, mit denen Sie weitere Interaktionen schreiben können, um erweiterte Abläufe Ihrer App zu optimieren. Das ist empfehlenswert, damit Sie die Leistung über den App-Start hinaus optimieren können.
In unserer Beispiel-App können Sie diese Abläufe so identifizieren:
- Starten Sie die Anwendung. Dies wird bereits teilweise durch die generierte Klasse abgedeckt.
- Warten Sie, bis die Inhalte asynchron geladen wurden.
- Scrolle durch die Liste der Snacks.
- Rufen Sie die Snack-Details auf.
Ändern Sie den Generator so, dass er die im folgenden Snippet beschriebenen Funktionen enthält, die die typischen Abläufe abdecken:
// ...
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
}
// ...
Schreiben Sie nun Interaktionen für jeden genannten Ablauf. Sie können sie als Erweiterungsfunktion von MacrobenchmarkScope schreiben, damit Sie Zugriff auf die Parameter und Funktionen haben, die sie bereitstellt. So können Sie die Interaktionen mit den Benchmarks wiederverwenden, um die Leistungssteigerungen zu überprüfen.
Auf asynchrone Inhalte warten
Viele Apps laden beim Starten Inhalte asynchron. Dieser Vorgang wird auch als vollständig angezeigter Zustand bezeichnet. Er gibt dem System an, wann die Inhalte geladen und gerendert wurden und der Nutzer mit ihnen interagieren kann. Warten Sie mit diesen Interaktionen auf den Status im Generator (waitForAsyncContent):
- Suchen Sie die Liste der Feed-Snacks.
- Warten Sie, bis einige Elemente in der Liste auf dem Bildschirm angezeigt werden.
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)
}
Scrollbare Liste
Für den Ablauf der scrollenden Snackliste (scrollSnackListJourney) können Sie diese Interaktionen ausführen:
- Suchen Sie nach dem UI-Element für die Snackliste.
- Legen Sie die Gestenränder so fest, dass die Systemsteuerung nicht ausgelöst wird.
- Scrollen Sie durch die Liste und warten Sie, bis die Benutzeroberfläche stabil ist.
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()
}
Zur Detailreise
Im letzten Journey (goToSnackDetailJourney) werden diese Interaktionen implementiert:
- Hier finden Sie die Liste der Snacks und alle Snack-Elemente, mit denen Sie arbeiten können.
- Wählen Sie ein Element aus der Liste aus.
- Klicken Sie auf das Element und warten Sie, bis der Detailbildschirm geladen ist. Sie können die Tatsache nutzen, dass die Snackliste nicht mehr auf dem Bildschirm angezeigt wird.
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)
}
Nachdem Sie alle Interaktionen definiert haben, die für die Ausführung Ihres Baseline Profile-Generators erforderlich sind, müssen Sie das Gerät definieren, auf dem er ausgeführt wird.
6. Gerät für die Ausführung des Generators vorbereiten
Zum Generieren von Baseline-Profilen empfehlen wir, entweder einen Emulator wie ein von Gradle verwaltetes Gerät oder ein Gerät mit Android 13 (API 33) oder höher zu verwenden.
Um den Prozess reproduzierbar zu machen und das Generieren von Baseline-Profilen zu automatisieren, können Sie verwaltete Gradle-Geräte verwenden. Mit Gradle Managed Devices können Sie Tests auf einem Android-Emulator ausführen, ohne ihn manuell starten und beenden zu müssen. Weitere Informationen zu von Gradle verwalteten Geräten finden Sie unter Tests mit von Gradle verwalteten Geräten skalieren.
Wenn Sie ein von Gradle verwaltetes Gerät definieren möchten, fügen Sie die Definition dem Modul :baselineprofile in der Datei build.gradle.kts hinzu, wie im folgenden Snippet gezeigt:
android {
// ...
testOptions.managedDevices.devices {
create<ManagedVirtualDevice>("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
In diesem Fall verwenden wir Android 11 (API-Level 31) und das aosp-Systemimage kann auf Root-Zugriff zugreifen.
Konfigurieren Sie als Nächstes das Baseline-Profil-Gradle-Plug-in so, dass das definierte Gradle-verwaltete Gerät verwendet wird. Fügen Sie dazu den Namen des Geräts in die Property managedDevices ein und deaktivieren Sie useConnectedDevices, wie im folgenden Snippet gezeigt:
android {
// ...
}
baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
}
dependencies {
// ...
}
Als Nächstes generieren Sie das Baseline-Profil.
7. Baseline-Profil erstellen
Sobald das Gerät bereit ist, können Sie das Baseline-Profil erstellen. Das Baseline-Profil-Gradle-Plug-in erstellt Gradle-Aufgaben, um den gesamten Prozess des Ausführens der Generator-Testklasse und des Anwendens der generierten Baseline-Profile in Ihrer App zu automatisieren.
Der neue Modulassistent hat eine Ausführungskonfiguration erstellt, mit der die Gradle-Aufgabe schnell mit allen erforderlichen Parametern ausgeführt werden kann, ohne dass zwischen dem Terminal und Android Studio gewechselt werden muss.
Suchen Sie die Generate Baseline Profile-Ausführungskonfiguration und klicken Sie auf die Schaltfläche „Ausführen“
, um sie auszuführen.

Mit der Aufgabe wird das zuvor definierte Emulator-Image gestartet. Führen Sie die Interaktionen aus der Testklasse BaselineProfileGenerator mehrmals aus, fahren Sie den Emulator anschließend herunter und stellen Sie die Ausgabe für Android Studio bereit.
Wenn der Generator erfolgreich abgeschlossen wurde, fügt das Gradle-Plug-in die generierte Datei baseline-prof.txt automatisch in der Zielanwendung (Modul :app) im Ordner src/release/generated/baselineProfile/ ein.

(Optional) Generator über die Befehlszeile ausführen
Alternativ können Sie den Generator über die Befehlszeile ausführen. Sie können die von Gradle Managed Device erstellte Aufgabe :app:generateBaselineProfile verwenden. Mit diesem Befehl werden alle Tests im Projekt ausgeführt, die durch die baselineProfile(project(:baselineProfile))-Abhängigkeit definiert sind. Da das Modul auch Benchmarks für die spätere Überprüfung der Leistungssteigerungen enthält, schlagen diese Tests mit einer Warnung vor dem Ausführen von Benchmarks auf einem Emulator fehl.
android .testInstrumentationRunnerArguments .androidx.benchmark.enabledRules=BaselineProfile
Dazu können Sie alle Generatoren von Baseline-Profilen mit dem folgenden Argument für den Instrumentierungsrunner filtern. Alle Benchmarks werden dann übersprungen:
Der vollständige Befehl sieht so aus:
./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
App mit Baseline-Profilen bereitstellen
Nachdem das Baseline-Profil generiert und in den Quellcode Ihrer App kopiert wurde, erstellen Sie die Produktionsversion Ihrer App wie gewohnt. Sie müssen nichts weiter tun, um die Baseline-Profile an Ihre Nutzer zu verteilen. Sie werden während des Builds vom Android-Gradle-Plug-in ausgewählt und in Ihr AAB oder APK aufgenommen. Laden Sie als Nächstes den Build in Google Play hoch.
Wenn Nutzer die App installieren oder von der vorherigen Version aktualisieren, wird auch das Baseline-Profil installiert. Das führt zu einer besseren Leistung ab dem ersten Ausführen der App.
Im nächsten Schritt wird beschrieben, wie Sie überprüfen können, wie stark sich die App-Leistung durch Baseline Profiles verbessert.
8. Optional: Generieren von Baseline-Profilen anpassen
Das Baseline Profiles Gradle-Plug-in enthält Optionen, mit denen Sie anpassen können, wie die Profile generiert werden, um Ihren spezifischen Anforderungen gerecht zu werden. Sie können das Verhalten mit dem Konfigurationsblock baselineProfile { } in Build-Skripten ändern.
Der Konfigurationsblock im Modul :baselineprofile wirkt sich darauf aus, wie die Generatoren ausgeführt werden. Sie können managedDevices hinzufügen und entscheiden, ob Sie useConnectedDevices oder von Gradle verwaltete Geräte verwenden möchten.
Der Konfigurationsblock im :app-Zielmodul bestimmt, wo die Profile gespeichert oder wie sie generiert werden. Sie können die folgenden Parameter ändern:
automaticGenerationDuringBuild: Wenn diese Option aktiviert ist, können Sie das Baseline-Profil beim Erstellen des Produktionsrelease-Builds generieren. Das ist hilfreich, wenn Sie Ihre App auf CI aufbauen, bevor Sie sie veröffentlichen.saveInSrc: Gibt an, ob die generierten Baseline-Profile im Ordnersrc/gespeichert werden. Alternativ können Sie über den Build-Ordner:baselineprofileauf die Datei zugreifen.baselineProfileOutputDir: Definiert, wo die generierten Baseline-Profile gespeichert werden sollen.mergeIntoMain: Standardmäßig werden Baseline-Profile pro Build-Variante (Produktvariante und Build-Typ) generiert. Wenn Sie alle Profile insrc/mainzusammenführen möchten, können Sie dieses Flag aktivieren.filter: Sie können filtern, welche Klassen oder Methoden in die generierten Baseline-Profile ein- oder ausgeschlossen werden sollen. Das kann für Bibliotheksentwickler hilfreich sein, die nur den Code aus der Bibliothek einfügen möchten.
9. Verbesserungen der Startleistung überprüfen
Nachdem Sie das Baseline-Profil generiert und Ihrer App hinzugefügt haben, sollten Sie prüfen, ob es die gewünschte Wirkung auf die Leistung Ihrer App hat.
Mit dem neuen Modul-Assistenten wird eine Benchmark-Klasse namens StartupBenchmarks erstellt. Es enthält einen Benchmark, mit dem die App-Startzeit gemessen und mit der Startzeit verglichen wird, wenn die App Baseline-Profile verwendet.
Die Klasse sieht so aus:
@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
}
)
}
}
Dazu wird MacrobenchmarkRule verwendet, mit dem Benchmarks für Ihre App ausgeführt und Leistungsmesswerte erfasst werden können. Der Einstiegspunkt zum Schreiben einer Benchmark ist die Funktion measureRepeated aus der Regel.
Dazu sind mehrere Parameter erforderlich:
packageName:welche Anwendung gemessen werden soll.metrics: Die Art der Informationen, die während des Benchmarks gemessen werden sollen.iterations: wie oft der Benchmark wiederholt wird.startupMode: Wie soll Ihre Anwendung beim Start des Benchmarks gestartet werden?setupBlock: Welche Interaktionen mit Ihrer App müssen vor der Messung erfolgen?measureBlock: Interaktionen mit Ihrer App, die Sie während des Benchmarks messen möchten.
Die Testklasse enthält außerdem zwei Tests: startupCompilationeNone() und startupCompilationBaselineProfiles(). Dabei wird die Funktion benchmark() mit unterschiedlichen compilationMode aufgerufen.
CompilationMode
Der Parameter CompilationMode definiert, wie die Anwendung in Maschinencode vorkompiliert wird. Es bietet die folgenden Optionen:
DEFAULT: Die App wird mithilfe von Baseline-Profilen teilweise vorkompiliert, sofern verfügbar. Diese Option wird verwendet, wenn keincompilationMode-Parameter angewendet wird.None(): Setzt den App-Kompilierungsstatus zurück und kompiliert die App nicht vorab. Die Just-in-time-Kompilierung (JIT) ist während der Ausführung der App weiterhin aktiviert.Partial(): Kompiliert die App mit Baseline-Profilen und/oder Warm-up-Läufen vor.Full(): kompiliert den gesamten Anwendungscode vorab. Dies ist die einzige Option unter Android 6 (API 23) und niedriger.
Wenn Sie mit der Optimierung der Anwendungsleistung beginnen möchten, können Sie den DEFAULT-Kompilierungsmodus auswählen, da die Leistung ähnlich ist wie bei der Installation der App über Google Play. Wenn Sie die Leistungsvorteile von Baseline-Profilen vergleichen möchten, können Sie die Ergebnisse der Kompilierungsmodi None und Partial vergleichen.
Benchmark zum Warten auf Inhalte ändern
Die Benchmarks werden ähnlich wie die Generatoren für Baseline-Profile geschrieben, indem Interaktionen mit Ihrer App geschrieben werden. Standardmäßig warten die erstellten Benchmarks nur darauf, dass der erste Frame gerendert wird – ähnlich wie bei BaselineProfileGenerator. Wir empfehlen daher, die Benchmarks so zu verbessern, dass sie auf asynchrone Inhalte warten.
Dazu können Sie die Erweiterungsfunktionen wiederverwenden, die Sie für den Generator schreiben. Da dieser Benchmark Startzeiten erfasst – mit StartupTimingMetric() –, empfehlen wir, hier nur das Warten auf die asynchronen Inhalte einzubeziehen und dann einen separaten Benchmark für die anderen im Generator definierten Nutzeraktionen zu schreiben.
// ...
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
}
Benchmarks ausführen
Sie können die Benchmarks auf dieselbe Weise ausführen wie instrumentierte Tests. Sie können die Testfunktion oder die gesamte Klasse mit dem Rinnensymbol daneben ausführen.

Achten Sie darauf, dass Sie ein physisches Gerät ausgewählt haben, da Benchmarks im Android-Emulator zur Laufzeit mit einer Warnung fehlschlagen, dass der Benchmark falsche Ergebnisse liefern kann. Sie können den Test zwar auf einem Emulator ausführen, messen dann aber die Leistung Ihres Hostcomputers. Bei starker Belastung werden Benchmarks langsamer ausgeführt und die Ergebnisse fallen umgekehrt aus.

Nachdem Sie den Benchmark ausgeführt haben, wird Ihre App neu erstellt und dann werden Ihre Benchmarks ausgeführt. Die Benchmarks starten, beenden und installieren Ihre App sogar mehrmals neu, basierend auf dem von Ihnen definierten iterations.
Nach Abschluss der Benchmarks können Sie die Zeitangaben in der Android Studio-Ausgabe sehen, wie im folgenden Screenshot dargestellt:

Auf dem Screenshot sehen Sie, dass die App-Startzeit für die einzelnen CompilationMode unterschiedlich ist. Die Medianwerte sind in der folgenden Tabelle aufgeführt:
timeToInitialDisplay [ms] | timeToFullDisplay [ms] | |
Keine | 202.2 | 818,8 |
BaselineProfiles | 193,7 | 637,9 |
Verbesserung | 4 % | 28% |
Der Unterschied zwischen den Kompilierungsmodi für timeToFullDisplay beträgt 180 ms. Das entspricht einer Verbesserung von etwa 28% allein durch die Verwendung eines Baseline-Profils. Das CompilationNone schneidet schlechter ab, weil das Gerät beim Start der App die meiste JIT-Kompilierung durchführen muss. Das CompilationBaselineProfiles schneidet besser ab, weil bei der teilweisen Kompilierung mit Baseline-Profilen der Code, den der Nutzer am wahrscheinlichsten verwendet, AOT-kompiliert wird. Der nicht kritische Code wird nicht vorkompiliert, sodass er nicht sofort geladen werden muss.
10. (Optional) Verbesserung der Scrollleistung überprüfen
Ähnlich wie im vorherigen Schritt können Sie die Scrollleistung messen und überprüfen. Erstellen Sie zuerst eine ScrollBenchmarks-Testklasse mit der Benchmark-Regel und zwei Testmethoden, die unterschiedliche Kompilierungsmodi verwenden:
@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
}
}
Verwenden Sie in der Methode scroll die Funktion measureRepeated mit den erforderlichen Parametern. Verwenden Sie für den Parameter metrics den Wert FrameTimingMetric. Damit wird gemessen, wie lange es dauert, UI-Frames zu rendern:
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
}
)
}
Dieses Mal müssen Sie die Interaktionen stärker zwischen setupBlock und measureBlock aufteilen, um die Framedauern nur während des ersten Layouts und des Scrollens der Inhalte zu messen. Setzen Sie die Funktionen, die den Standardbildschirm starten, in setupBlock und die bereits erstellten Erweiterungsfunktionen waitForAsyncContent() und 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()
}
)
}
Sobald der Benchmark bereit ist, können Sie ihn wie zuvor ausführen, um Ergebnisse wie im folgenden Screenshot zu erhalten:

Die FrameTimingMetric-Ausgabe gibt die Dauer von Frames in Millisekunden (frameDurationCpuMs) im 50., 90., 95. und 99. Perzentil an. Unter Android 12 (API-Level 31) und höher wird auch zurückgegeben, wie viel Zeit Ihre Frames über dem Limit liegen (frameOverrunMs). Der Wert kann negativ sein. Das bedeutet, dass für die Erstellung des Frames zusätzliche Zeit zur Verfügung stand.
Aus den Ergebnissen geht hervor, dass das CompilationBaselineProfiles im Durchschnitt eine um 2 ms kürzere Frame-Dauer hat, was für Nutzer möglicherweise nicht spürbar ist. Bei den anderen Perzentilen sind die Ergebnisse jedoch deutlicher. Für P99 beträgt die Differenz 43, 5 ms, was mehr als 3 übersprungenen Frames auf einem Gerät mit 90 fps entspricht. Beim Pixel 6 sind das beispielsweise 1.000 ms / 90 FPS = ~11 ms maximale Zeit zum Rendern eines Frames.
11. Glückwunsch
Herzlichen Glückwunsch! Sie haben dieses Codelab erfolgreich abgeschlossen und die Leistung Ihrer App mit Baseline-Profilen verbessert.
Zusätzliche Ressourcen
Weitere Ressourcen:
- App-Leistung mit Macrobenchmark prüfen: Codelab, in dem Benchmarking genauer behandelt wird.
- Leistungsbeispiele: Repository mit Makrobenchmarks und anderen Leistungsbeispielen.
- Now In Android-Beispiel-App: Eine Anwendung aus der Praxis, in der Benchmarking und Baseline-Profile zur Leistungsverbesserung verwendet werden.