Fehlerbehebung bei Referenzprofilen

In diesem Dokument finden Sie Best Practices und Schritte zur Fehlerbehebung, mit denen Sie Probleme diagnostizieren und dafür sorgen können, dass Ihre Baseline-Profile ordnungsgemäß funktionieren und den größtmöglichen Nutzen bieten.

Probleme beim Erstellen

Wenn Sie das Beispiel für Baseline-Profile in der Beispiel-App Now in Android kopiert haben, treten möglicherweise Testfehler während der Baseline-Profil-Aufgabe auf, die besagen, dass die Tests nicht auf einem Emulator ausgeführt werden können:

./gradlew assembleDemoRelease
Starting a Gradle Daemon (subsequent builds will be faster)
Calculating task graph as no configuration cache is available for tasks: assembleDemoRelease
Type-safe project accessors is an incubating feature.

> Task :benchmarks:pixel6Api33DemoNonMinifiedReleaseAndroidTest
Starting 14 tests on pixel6Api33

com.google.samples.apps.nowinandroid.foryou.ScrollForYouFeedBenchmark > scrollFeedCompilationNone[pixel6Api33] FAILED
        java.lang.AssertionError: ERRORS (not suppressed): EMULATOR
        WARNINGS (suppressed):
        ...

Die Fehler treten auf, weil Now in Android ein von Gradle verwaltetes Gerät für die Generierung von Baseline-Profilen verwendet. Die Fehler sind zu erwarten, da Sie in der Regel keine Leistungsbenchmarks auf einem Emulator ausführen sollten. Da Sie beim Generieren von Baseline-Profilen jedoch keine Leistungsmesswerte erheben, können Sie die Erhebung von Baseline-Profilen auf Emulatoren ausführen. Wenn Sie Baseline Profiles mit einem Emulator verwenden möchten, führen Sie den Build und die Installation über die Befehlszeile aus und legen Sie ein Argument fest, um Baseline Profiles-Regeln zu aktivieren:

installDemoRelease -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

Alternativ können Sie in Android Studio eine benutzerdefinierte Ausführungskonfiguration erstellen, um Baseline-Profile auf Emulatoren zu aktivieren. Wählen Sie dazu Run > Edit Configurations aus:

Benutzerdefinierte Laufzeitkonfiguration zum Erstellen von Baseline-Profilen in Now in Android hinzufügen
Abbildung 1: Fügen Sie eine benutzerdefinierte Laufzeitkonfiguration hinzu, um Baseline-Profile in Now in Android zu erstellen.

Profilinstallation und -anwendung überprüfen

So prüfen Sie, ob das APK oder Android App Bundle (AAB), das Sie untersuchen, aus einer Build-Variante stammt, die Baseline Profiles enthält:

  1. Wählen Sie in Android Studio Build > Analyze APK aus.
  2. Öffnen Sie Ihr AAB oder APK.
  3. Prüfen Sie, ob die Datei baseline.prof vorhanden ist:

    • Wenn Sie ein AAB untersuchen, befindet sich das Profil unter /BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof.
    • Wenn Sie ein APK untersuchen, befindet sich das Profil unter /assets/dexopt/baseline.prof.

      Das Vorhandensein dieser Datei ist das erste Anzeichen für eine korrekte Build-Konfiguration. Wenn sie fehlt, erhält die Android-Laufzeit bei der Installation keine Vorabkompilierungsanweisungen.

      Mit dem APK Analyzer in Android Studio nach einem Baseline Profile suchen
      Abbildung 2: Mit dem APK Analyzer in Android Studio können Sie prüfen, ob ein Baseline Profile vorhanden ist.

Baseline-Profile müssen auf dem Gerät kompiliert werden, auf dem die App ausgeführt wird. Wenn Sie nicht debugfähige Builds mit Android Studio oder dem Gradle-Wrapper-Befehlszeilentool installieren, erfolgt die On-Device-Kompilierung automatisch. Wenn Sie die App aus dem Google Play Store installieren, werden Baseline Profiles während der Hintergrundaktualisierungen des Geräts und nicht bei der Installation kompiliert. Wenn die App mit anderen Tools installiert wird, ist die Jetpack-Bibliothek ProfileInstaller dafür verantwortlich, die Profile für die Kompilierung während des nächsten DEX-Optimierungsprozesses im Hintergrund in die Warteschlange zu stellen.

Wenn Sie in diesen Fällen sichergehen möchten, dass Ihre Baseline-Profile verwendet werden, müssen Sie möglicherweise die Kompilierung von Baseline-Profilen erzwingen. Mit ProfileVerifier können Sie den Status der Profilinstallation und -kompilierung abfragen, wie im folgenden Beispiel gezeigt:

Kotlin

private const val TAG = "MainActivity"

class MainActivity : ComponentActivity() {
  ...
  override fun onResume() {
    super.onResume()
    lifecycleScope.launch {
      logCompilationStatus()
    }
  }

  private suspend fun logCompilationStatus() {
     withContext(Dispatchers.IO) {
        val status = ProfileVerifier.getCompilationStatusAsync().await()
        when (status.profileInstallResultCode) {
            RESULT_CODE_NO_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Baseline Profile not found")
            RESULT_CODE_COMPILED_WITH_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Compiled with profile")
            RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING ->
                Log.d(TAG, "ProfileInstaller: App was installed through Play store")
            RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST ->
                Log.d(TAG, "ProfileInstaller: PackageName not found")
            RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ ->
                Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read")
            RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE ->
                Log.d(TAG, "ProfileInstaller: Can't write cache file")
            RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            else ->
                Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued")
        }
    }
}

Java

public class MainActivity extends ComponentActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onResume() {
        super.onResume();

        logCompilationStatus();
    }

    private void logCompilationStatus() {
         ListeningExecutorService service = MoreExecutors.listeningDecorator(
                Executors.newSingleThreadExecutor());
        ListenableFuture<ProfileVerifier.CompilationStatus> future =
                ProfileVerifier.getCompilationStatusAsync();
        Futures.addCallback(future, new FutureCallback<>() {
            @Override
            public void onSuccess(CompilationStatus result) {
                int resultCode = result.getProfileInstallResultCode();
                if (resultCode == RESULT_CODE_NO_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Baseline Profile not found");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Compiled with profile");
                } else if (resultCode == RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING) {
                    Log.d(TAG, "ProfileInstaller: App was installed through Play store");
                } else if (resultCode == RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST) {
                    Log.d(TAG, "ProfileInstaller: PackageName not found");
                } else if (resultCode == RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ) {
                    Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read");
                } else if (resultCode
                        == RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE) {
                    Log.d(TAG, "ProfileInstaller: Can't write cache file");
                } else if (resultCode == RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else {
                    Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued");
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Log.d(TAG,
                        "ProfileInstaller: Error getting installation status: " + t.getMessage());
            }
        }, service);
    }
}

Die folgenden Ergebniscodes geben Hinweise auf die Ursache einiger Probleme:

RESULT_CODE_COMPILED_WITH_PROFILE
Das Profil wird installiert, kompiliert und immer verwendet, wenn die App ausgeführt wird. Das ist das gewünschte Ergebnis.
RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED
Im ausgeführten APK wurde kein Profil gefunden. Achten Sie darauf, dass Sie eine Build-Variante verwenden, die Baseline-Profile enthält, wenn dieser Fehler auftritt, und dass das APK ein Profil enthält.
RESULT_CODE_NO_PROFILE
Bei der Installation der App über den App-Store oder den Paketmanager wurde kein Profil für diese App installiert. Der Hauptgrund für diesen Fehlercode ist, dass das Profilinstallationsprogramm nicht ausgeführt wurde, weil ProfileInstallerInitializer deaktiviert ist. Wenn dieser Fehler gemeldet wird, ist im APK der Anwendung weiterhin ein eingebettetes Profil vorhanden. Wenn ein eingebettetes Profil nicht gefunden wird, wird der Fehlercode RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED zurückgegeben.
RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION
Ein Profil wird im APK oder AAB gefunden und in die Warteschlange für die Kompilierung gestellt. Wenn ein Profil von ProfileInstaller installiert wird, wird es für die Kompilierung in die Warteschlange gestellt, wenn das System das nächste Mal die DEX-Optimierung im Hintergrund ausführt. Das Profil ist erst aktiv, wenn die Kompilierung abgeschlossen ist. Führen Sie keine Benchmarks für Ihre Baseline-Profile aus, bevor die Kompilierung abgeschlossen ist. Möglicherweise müssen Sie die Kompilierung von Baseline-Profilen erzwingen. Dieser Fehler tritt nicht auf, wenn die App über den Play Store oder den Paketmanager auf Geräten mit Android 9 (API 28) und höher installiert wird, da die Kompilierung während der Installation erfolgt.
RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
Ein nicht übereinstimmendes Profil ist installiert und die App wurde damit kompiliert. Dies ist das Ergebnis der Installation über den Google Play Store oder den Paketmanager. Dieses Ergebnis unterscheidet sich von RESULT_CODE_COMPILED_WITH_PROFILE, da im nicht übereinstimmenden Profil nur Methoden kompiliert werden, die weiterhin zwischen dem Profil und der App geteilt werden. Das Profil ist effektiv kleiner als erwartet und es werden weniger Methoden kompiliert als im Baseline-Profil enthalten waren.
RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE
ProfileVerifier kann die Cache-Datei mit dem Bestätigungsergebnis nicht schreiben. Das kann entweder passieren, weil etwas mit den Berechtigungen für den App-Ordner nicht stimmt oder weil auf dem Gerät nicht genügend freier Speicherplatz vorhanden ist.
RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION
ProfileVerifieris running on an unsupported API version of Android. ProfileVerifier wird nur unter Android 9 (API‑Level 28) und höher unterstützt.
RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST
Eine PackageManager.NameNotFoundException wird ausgelöst, wenn die PackageManager für das App-Paket abgefragt wird. Das sollte nur selten vorkommen. Deinstalliere die App und installiere alles neu.
RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ
Es ist eine Datei mit dem Cache eines vorherigen Bestätigungsergebnisses vorhanden, die aber nicht gelesen werden kann. Das sollte nur selten vorkommen. Deinstalliere die App und installiere alles neu.

ProfileVerifier in der Produktion verwenden

In der Produktionsumgebung können Sie ProfileVerifier in Verbindung mit Analyseberichtsbibliotheken wie Google Analytics for Firebase verwenden, um Analyseereignisse zu generieren, die den Profilstatus angeben. So werden Sie beispielsweise schnell benachrichtigt, wenn eine neue App-Version veröffentlicht wird, die keine Baseline-Profile enthält.

Kompilierung von Baseline-Profilen erzwingen

Wenn der Kompilierungsstatus Ihrer Baseline-Profile RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION ist, können Sie die sofortige Kompilierung mit adb erzwingen:

adb shell cmd package compile -r bg-dexopt PACKAGE_NAME

Kompilierungsstatus des Baseline-Profils ohne ProfileVerifier prüfen

Wenn Sie ProfileVerifier nicht verwenden, können Sie den Kompilierungsstatus mit adb prüfen. Allerdings erhalten Sie damit nicht so detaillierte Informationen wie mit ProfileVerifier:

adb shell dumpsys package dexopt | grep -A 2 PACKAGE_NAME

Die Verwendung von adb führt zu einer Ausgabe, die etwa so aussieht:

  [com.google.samples.apps.nowinandroid.demo]
    path: /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/base.apk
      arm64: [status=speed-profile] [reason=bg-dexopt] [primary-abi]
        [location is /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/oat/arm64/base.odex]

Der Statuswert gibt den Status der Profilkompilierung an und kann einen der folgenden Werte haben:

Status der Zusammenstellung Bedeutung
speed‑profile Ein kompiliertes Profil ist vorhanden und wird verwendet.
verify Es ist kein kompiliertes Profil vorhanden.

Der Status verify bedeutet nicht, dass das APK oder AAB kein Profil enthält, da es für die Kompilierung durch den nächsten DEX-Optimierungsvorgang im Hintergrund in die Warteschlange gestellt werden kann.

Der Grundwert gibt an, wodurch die Kompilierung des Profils ausgelöst wird. Er kann einen der folgenden Werte haben:

Grund Bedeutung
install‑dm Ein Baseline-Profil wurde manuell oder von Google Play bei der Installation der App erstellt.
bg‑dexopt Ein Profil wurde erstellt, während Ihr Gerät inaktiv war. Das kann ein Baseline-Profil oder ein Profil sein, das während der App-Nutzung erfasst wurde.
cmdline Die Kompilierung wurde über adb ausgelöst. Das kann ein Baseline-Profil oder ein Profil sein, das während der App-Nutzung erfasst wurde.

Startup-Profilanwendung für DEX und r8.json überprüfen

Startup Profile-Regeln werden zur Build-Zeit von R8 verwendet, um das Layout von Klassen in Ihren DEX-Dateien zu optimieren. Diese Optimierung zur Build-Zeit unterscheidet sich von der Verwendung von Baseline-Profilen (baseline.prof), da diese im APK oder AAB enthalten sind, damit ART die On-Device-Kompilierung durchführen kann. Da Startup Profile-Regeln während des Build-Prozesses angewendet werden, gibt es in Ihrem APK oder AAB keine separate startup.prof-Datei, die Sie prüfen können. Die Auswirkungen von Startup-Profilen sind stattdessen im DEX-Dateilayout sichtbar.

DEX-Anordnung mit r8.json prüfen (empfohlen für AGP 8.8 oder höher)

Bei Projekten, die das Android-Gradle-Plug-in (AGP) 8.8 oder höher verwenden, können Sie prüfen, ob das Startprofil angewendet wurde, indem Sie die generierte Datei r8.json untersuchen. Diese Datei ist in Ihrem AAB enthalten.

  1. Öffnen Sie Ihr AAB-Archiv und suchen Sie nach der Datei r8.json.
  2. Suchen Sie in der Datei nach dem dexFiles-Array, in dem die generierten DEX-Dateien aufgeführt sind.
  3. Suchen Sie nach einem dexFiles-Objekt, das das Schlüssel/Wert-Paar "startup": true enthält. Dies gibt explizit an, dass die Regeln des Startup-Profils angewendet wurden, um das Layout dieser DEX-Datei zu optimieren.

    "dexFiles": [
     {
       "checksum": "...",
       "startup": true // This flag confirms profile application to this DEX file
     },
     // ... other DEX files
    ]
    

DEX-Anordnung für alle AGP-Versionen prüfen

Wenn Sie eine AGP-Version unter 8.8 verwenden, ist die Überprüfung der DEX-Dateien die primäre Methode, um zu prüfen, ob Ihr Startprofil korrekt angewendet wurde. Sie können diese Methode auch verwenden, wenn Sie AGP 8.8 oder höher verwenden und das DEX-Layout manuell prüfen möchten. Das kann beispielsweise der Fall sein, wenn Sie nicht die erwarteten Leistungssteigerungen sehen. So prüfen Sie die DEX-Anordnung:

  1. Öffnen Sie Ihr AAB oder APK in Android Studio über Build > Analyze APK (Build > APK analysieren).
  2. Gehen Sie zur ersten DEX-Datei. Beispiel: classes.dex.
  3. Prüfen Sie den Inhalt dieser DEX-Datei. Sie sollten überprüfen können, ob die kritischen Klassen und Methoden, die in der Datei mit dem Startup-Profil (startup-prof.txt) definiert sind, in dieser primären DEX-Datei vorhanden sind. Bei einer erfolgreichen Bewerbung werden diese für Start-ups wichtigen Komponenten für ein schnelleres Laden priorisiert.

Leistungsprobleme

In diesem Abschnitt finden Sie einige Best Practices zum korrekten Definieren und Benchmarking Ihrer Baseline-Profile, damit Sie sie optimal nutzen können.

Startup-Messwerte richtig vergleichen

Baseline-Profile sind effektiver, wenn Ihre Startmesswerte gut definiert sind. Die beiden wichtigsten Messwerte sind die Zeit bis zur ersten Anzeige (Time to Initial Display, TTID) und die Zeit bis zur vollständigen Anzeige (Time to Full Display, TTFD).

TTID ist der Zeitpunkt, an dem die App den ersten Frame rendert. Es ist wichtig, dass dieser Vorgang so kurz wie möglich ist, da die Anzeige dem Nutzer signalisiert, dass die App ausgeführt wird. Sie können sogar eine unbestimmte Fortschrittsanzeige einblenden, um zu zeigen, dass die App reagiert.

TTFD ist der Zeitpunkt, zu dem mit der App interagiert werden kann. Es ist wichtig, diesen Vorgang so kurz wie möglich zu halten, um Frustration bei den Nutzern zu vermeiden. Wenn Sie TTFD korrekt signalisieren, teilen Sie dem System mit, dass der Code, der auf dem Weg zu TTFD ausgeführt wird, Teil des App-Starts ist. Daher wird dieser Code mit höherer Wahrscheinlichkeit im Profil platziert.

Halten Sie sowohl TTID als auch TTFD so niedrig wie möglich, damit Ihre App reaktionsschnell wirkt.

Das System kann die TTID erkennen, in Logcat anzeigen und als Teil der Startup-Benchmarks melden. Das System kann die TTFD jedoch nicht ermitteln. Es liegt in der Verantwortung der App, zu melden, wenn sie einen vollständig gerenderten interaktiven Zustand erreicht. Dazu können Sie reportFullyDrawn() oder ReportDrawn aufrufen, wenn Sie Jetpack Compose verwenden. Wenn Sie mehrere Hintergrundaufgaben haben, die alle abgeschlossen sein müssen, bevor die App als vollständig gerendert gilt, können Sie FullyDrawnReporter verwenden, wie unter Genauigkeit der Startzeit verbessern beschrieben.

Bibliotheksprofile und benutzerdefinierte Profile

Beim Benchmarking der Auswirkungen von Profilen kann es schwierig sein, die Vorteile der Profile Ihrer App von Profilen zu trennen, die von Bibliotheken wie Jetpack-Bibliotheken beigetragen werden. Wenn Sie Ihr APK erstellen, fügt das Android-Gradle-Plug-in alle Profile in Bibliotheksabhängigkeiten sowie Ihr benutzerdefiniertes Profil hinzu. Das ist gut für die Optimierung der Gesamtleistung und wird für Ihre Release-Builds empfohlen. Es ist jedoch schwierig zu messen, wie viel zusätzliche Leistung durch Ihr benutzerdefiniertes Profil erzielt wird.

Eine schnelle Möglichkeit, die zusätzliche Optimierung durch Ihr benutzerdefiniertes Profil manuell zu prüfen, besteht darin, es zu entfernen und Ihre Benchmarks auszuführen. Tauschen Sie es dann aus und führen Sie die Benchmarks noch einmal aus. Wenn Sie die beiden vergleichen, sehen Sie die Optimierungen, die nur durch die Bibliotheksprofile und durch die Bibliotheksprofile plus Ihr benutzerdefiniertes Profil erzielt werden.

Eine automatisierbare Möglichkeit, Profile zu vergleichen, besteht darin, eine neue Build-Variante zu erstellen, die nur die Bibliotheksprofile und nicht Ihr benutzerdefiniertes Profil enthält. Vergleichen Sie die Benchmarks dieser Variante mit der Release-Variante, die sowohl die Bibliotheksprofile als auch Ihre benutzerdefinierten Profile enthält. Im folgenden Beispiel wird gezeigt, wie Sie die Variante einrichten, die nur Bibliotheksprofile enthält. Fügen Sie Ihrem Profil-Consumer-Modul, das in der Regel Ihr App-Modul ist, eine neue Variante mit dem Namen releaseWithoutCustomProfile hinzu:

Kotlin

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    create("releaseWithoutCustomProfile") {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile(project(":baselineprofile"))
}

baselineProfile {
  variants {
    create("release") {
      from(project(":baselineprofile"))
    }
  }
}

Groovy

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    releaseWithoutCustomProfile {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile ':baselineprofile"'
}

baselineProfile {
  variants {
    release {
      from(project(":baselineprofile"))
    }
  }
}

Im vorherigen Codebeispiel wird die baselineProfile-Abhängigkeit aus allen Varianten entfernt und nur auf die release-Variante angewendet. Es mag kontraintuitiv erscheinen, dass die Bibliotheksprofile weiterhin hinzugefügt werden, wenn die Abhängigkeit vom Profilerstellungsmodul entfernt wird. Dieses Modul ist jedoch nur für die Generierung Ihres benutzerdefinierten Profils verantwortlich. Das Android-Gradle-Plug-in wird weiterhin für alle Varianten ausgeführt und ist für das Einbeziehen von Bibliotheksprofilen verantwortlich.

Außerdem müssen Sie die neue Variante dem Profilgeneratormodul hinzufügen. In diesem Beispiel heißt das Producer-Modul :baselineprofile.

Kotlin

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      create("releaseWithoutCustomProfile") {}
      ...
    }
  ...
}

Groovy

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      releaseWithoutCustomProfile {}
      ...
    }
  ...
}

Wenn Sie den Benchmark in Android Studio ausführen, wählen Sie eine releaseWithoutCustomProfile-Variante aus, um die Leistung nur mit Bibliotheksprofilen zu messen, oder eine release-Variante, um die Leistung mit Bibliotheks- und benutzerdefinierten Profilen zu messen.

I/O-gebundene App-Starts vermeiden

Wenn Ihre App während des Starts viele E/A- oder Netzwerkaufrufe ausführt, kann sich das negativ auf die Startzeit der App und die Genauigkeit des Start-Benchmarkings auswirken. Diese aufwendigen Aufrufe können eine unbestimmte Zeit in Anspruch nehmen, die sich im Laufe der Zeit und sogar zwischen den Iterationen desselben Benchmarks ändern kann. I/O-Aufrufe sind in der Regel besser als Netzwerkaufrufe, da letztere von Faktoren beeinflusst werden können, die außerhalb des Geräts und auf dem Gerät selbst liegen. Vermeiden Sie Netzwerkaufrufe beim Start. Wenn die Verwendung einer der beiden Optionen unvermeidlich ist, verwenden Sie I/O.

Wir empfehlen, die App-Architektur so zu gestalten, dass die App auch ohne Netzwerk- oder E/A-Aufrufe gestartet werden kann, auch wenn dies nur für das Benchmarking des Starts verwendet wird. So wird die geringstmögliche Variabilität zwischen verschiedenen Iterationen Ihrer Benchmarks erreicht.

Wenn Ihre App Hilt verwendet, können Sie beim Benchmarking in Microbenchmark und Hilt gefälschte E/A-gebundene Implementierungen bereitstellen.

Alle wichtigen Nutzerpfade abdecken

Es ist wichtig, dass Sie alle wichtigen User Journeys bei der Erstellung Ihres Baseline-Profils genau abdecken. User Journeys, die nicht abgedeckt sind, werden durch Baseline-Profile nicht verbessert. Die effektivsten Baseline-Profile umfassen alle gängigen User Journeys für den Start sowie leistungsbezogene In-App-User Journeys wie das Scrollen von Listen.

A/B-Tests für Änderungen am Kompilierzeitprofil

Da Startup- und Baseline-Profile eine Optimierung zur Kompilierungszeit sind, wird das direkte A/B-Testen verschiedener APKs über den Google Play Store für Produktionsreleases im Allgemeinen nicht unterstützt. Um die Auswirkungen in einer produktionsähnlichen Umgebung zu bewerten, können Sie die folgenden Ansätze in Betracht ziehen:

  • Release außerhalb des Zyklus: Laden Sie ein Release außerhalb des Zyklus für einen kleinen Prozentsatz Ihrer Nutzer hoch, das nur die Profiländerung enthält. So können Sie Messwerte für den Leistungsunterschied in der Praxis erfassen.

  • Lokales Benchmarking: Führen Sie ein lokales Benchmarking Ihrer App mit und ohne angewendetes Profil durch. Lokale Benchmarks zeigen jedoch das Best-Case-Szenario für Profile, da sie nicht die Auswirkungen von Cloud-Profilen aus ART enthalten, die auf Produktionsgeräten vorhanden sind.