Wir empfehlen dringend, die Generierung von Profilregeln mit der Jetpack Macrobenchmark-Bibliothek zu automatisieren, um den manuellen Aufwand zu reduzieren und die allgemeine Skalierbarkeit zu erhöhen. Sie können jedoch Profile manuell erstellen und Regeln für sie in Ihrer App messen.
Profilregeln manuell definieren
Sie können Profilregeln manuell in einer App oder einem Bibliotheksmodul definieren, indem Sie im Verzeichnis src/main
eine Datei namens baseline-prof.txt
erstellen. Dies ist derselbe Ordner, der die Datei AndroidManifest.xml
enthält.
Die Datei enthält eine Regel pro Zeile. Jede Regel stellt ein Muster für übereinstimmende Methoden oder Klassen in der App oder Bibliothek dar, die optimiert werden müssen.
Die Syntax dieser Regeln ist ein Superset des menschenlesbaren ART-Profilformats (HRF), wenn adb shell profman --dump-classes-and-methods
verwendet wird. Die Syntax ähnelt der Syntax für Deskriptoren und Signaturen, ermöglicht aber die Verwendung von Platzhaltern, um das Erstellen von Regeln zu vereinfachen.
Das folgende Beispiel zeigt einige Baseline-Profilregeln, die in der Jetpack Compose-Bibliothek enthalten sind:
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;
Sie können versuchen, Profilregeln in diesem Beispielprojekt im Compiler Explorer zu ändern. Hinweis: Der Compiler Explorer unterstützt nur das visuell lesbare ART-Profilformat (HRF). Platzhalter werden daher nicht unterstützt.
Syntax von Regeln
Diese Regeln können auf zwei Arten erstellt werden, um entweder auf Methoden oder Klassen ausgerichtet zu werden:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Eine Klassenregel hat das folgende Muster:
[CLASS_DESCRIPTOR]
Eine detaillierte Beschreibung finden Sie in der folgenden Tabelle:
Syntax | Beschreibung |
---|---|
FLAGS |
Stellt eines oder mehrere der Zeichen H , S und P dar, um anzugeben, ob diese Methode in Bezug auf den Starttyp als Hot , Startup oder Post Startup gekennzeichnet werden muss. Eine Methode mit dem Flag H ist eine „heiße“ Methode, d. h., sie wird während der Lebensdauer der App häufig aufgerufen. Eine Methode mit dem Flag S ist eine Methode, die beim Start aufgerufen wird. Eine Methode mit dem Flag P gibt an, dass sie nach dem Start aufgerufen wird. Eine in dieser Datei vorhandene Klasse gibt an, dass sie beim Start verwendet wird und im Heap vorab zugewiesen werden muss, um die Kosten für das Laden der Klasse zu vermeiden. Der ART-Compiler verwendet verschiedene Optimierungsstrategien, z. B. die AOT-Kompilierung dieser Methoden und die Durchführung von Layoutoptimierungen in der generierten AOT-Datei. |
CLASS_DESCRIPTOR |
Deskriptor für die Klasse der anvisierten Methode. Beispiel: androidx.compose.runtime.SlotTable hat den Descriptor Landroidx/compose/runtime/SlotTable; . L wird hier gemäß dem Dalvik Executable (DEX)-Format vorangestellt. |
METHOD_SIGNATURE |
Signatur der Methode, einschließlich Name, Parametertypen und Rückgabetypen der Methode. Beispiel:// LayoutNode.kt fun isPlaced():Boolean { // ... } auf LayoutNode hat die Signatur isPlaced()Z . |
Diese Muster können Platzhalter enthalten, damit eine einzelne Regel mehrere Methoden oder Klassen umfassen kann. Eine Anleitung zum Schreiben mit Regelsyntax in Android Studio finden Sie im Plug-in Android-Baseline-Profile.
Ein Beispiel für eine Platzhalterregel könnte so aussehen:
HSPLandroidx/compose/ui/layout/**->**(**)**
Unterstützte Typen in Regeln für Baseline-Profile
Für Regeln für Baseline-Profile werden die folgenden Typen unterstützt. Weitere Informationen zu diesen Typen finden Sie im Artikel zum Dalvik Executable (DEX)-Format.
Zeichen | Eingeben | Beschreibung |
---|---|---|
B |
Byte | Signiertes Byte |
C |
char | Unicode-Zeichencodepunkt, codiert in UTF-16 |
D |
Doppelt | Gleitkommawert mit doppelter Genauigkeit |
F |
float | Gleitkommawert mit einfacher Genauigkeit |
I |
int | Ganzzahl |
J |
long | Ganzzahl mit hoher Präzision |
S |
kurz | Signierte Kurzform |
V |
void | Ungültig |
Z |
Boolesch | Richtig oder falsch? |
L (Klassenname) |
Referenz | Eine Instanz eines Klassennamens |
Außerdem können Bibliotheken Regeln definieren, die in AAR-Artefakten verpackt sind. Wenn Sie ein APK erstellen, das diese Artefakte enthält, werden die Regeln ähnlich wie beim Zusammenführen von Manifesten zusammengeführt und in ein kompaktes binäres ART-Profil kompiliert, das für das APK spezifisch ist.
ART nutzt dieses Profil, wenn das APK auf Geräten verwendet wird, um bei der Installation unter Android 9 (API-Ebene 28) oder Android 7 (API-Ebene 24) bei Verwendung von ProfileInstaller
einen bestimmten Teil der App AOT zu kompilieren.
Baseline-Profile manuell erfassen
Sie können ein Baseline-Profil manuell generieren, ohne die Macrobenchmark-Bibliothek einzurichten, und UI-Automatisierungen für Ihre kritischen User Journeys erstellen. Wir empfehlen zwar die Verwendung von Makrobenchmarks, dies ist jedoch nicht immer möglich. Wenn Sie beispielsweise kein Gradle-Buildsystem verwenden, können Sie das Gradle-Plug-in für das Baseline-Profil nicht verwenden. In solchen Fällen können Sie Baseline-Profilregeln manuell erfassen. Das ist viel einfacher, wenn Sie ein Gerät oder einen Emulator mit API 34 und höher verwenden. Bei niedrigeren API-Ebenen ist dies zwar auch möglich, erfordert aber Root-Zugriff und Sie müssen einen Emulator mit einem AOSP-Image verwenden. So erfassen Sie Regeln direkt:
- Installieren Sie eine Releaseversion Ihrer App auf einem Testgerät. Der Buildtyp der App muss für ein genaues Profil R8-optimiert und nicht debugbar sein.
- Die Profile dürfen nicht bereits kompiliert sein.
API 34 und höher
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
API 33 und niedriger
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Wenn Ihr APK von der Profile Installer-Bibliothek von Jetpack abhängig ist, wird beim ersten Start Ihres APKs ein Profil gestartet. Dies kann die Profilgenerierung beeinträchtigen. Deaktivieren Sie es daher mit dem folgenden Befehl:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
- Führen Sie die App aus und führen Sie die kritischen User Journeys manuell aus, für die Sie ein Profil erstellen möchten.
- ART auffordern, die Profile zu dumpen. Wenn Ihr APK von der Jetpack-Bibliothek „Profile Installer“ abhängig ist, können Sie die Profile damit dumpen:
adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
Wenn Sie den Profile Installer nicht verwenden, können Sie die Profile mit dem folgenden Befehl manuell in einem Emulator dumpen:adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME adb shell am force-stop $PACKAGE_NAME
- Warten Sie mindestens fünf Sekunden, bis die Profilgenerierung abgeschlossen ist.
- Konvertieren Sie die generierten Binärprofile in Text:
API 34 und höher
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
API 33 und niedriger
Prüfen Sie, ob ein Referenzprofil oder ein aktuelles Profil erstellt wurde. Ein Referenzprofil befindet sich an folgendem Speicherort:
/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Ein aktuelles Profil befindet sich an folgendem Speicherort:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Speicherort des APK ermitteln:
adb root adb shell pm path $PACKAGE_NAME
Führen Sie die Umwandlung aus:
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
- Rufen Sie das gedumpte Profil mit
adb
vom Gerät ab:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Dadurch werden die generierten Profilregeln abgerufen und in Ihrem App-Modul installiert. Wenn Sie die App das nächste Mal erstellen, wird das Baseline-Profil eingeschlossen. Führen Sie dazu die Schritte unter Installationsprobleme aus.
App-Verbesserungen manuell messen
Wir empfehlen Ihnen dringend, App-Verbesserungen durch Benchmarking zu messen. Wenn Sie die Verbesserungen jedoch manuell messen möchten, können Sie als Referenz den Start der nicht optimierten App messen.
PACKAGE_NAME=com.example.app
# Force Stop App adb shell am force-stop $PACKAGE_NAME # Reset compiled state adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup # This corresponds to `Time to initial display` metric. adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Laden Sie als Nächstes das Baseline-Profil per Sideload herunter.
# Unzip the Release APK first. unzip release.apk
# Create a ZIP archive. # The name should match the name of the APK. # Copy `baseline.prof{m}` and rename it `primary.prof{m}`. cp assets/dexopt/baseline.prof primary.prof cp assets/dexopt/baseline.profm primary.profm
# Create an archive. zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files: unzip -l release.dm # Archive: release.dm # Length Date Time Name # --------- ---------- ----- ---- # 3885 1980-12-31 17:01 primary.prof # 1024 1980-12-31 17:01 primary.profm # --------- ------- # 2 files
# Install APK + Profile together. adb install-multiple release.apk release.dm
Führen Sie den folgenden Befehl aus, um zu prüfen, ob das Paket bei der Installation optimiert wurde:
# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME
Die Ausgabe muss angeben, dass das Paket kompiliert wurde:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Sie können die Leistung beim Starten der App jetzt wie gewohnt messen, ohne den kompilierten Status zurückzusetzen. Achten Sie darauf, den kompilierten Status für das Paket nicht zurückzusetzen.
# Force stop app adb shell am force-stop $PACKAGE_NAME
# Measure app startup adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Baseline-Profile und profgen
In diesem Abschnitt wird beschrieben, was das Tool profgen beim Erstellen einer kompakten Binärversion eines Baseline-Profils tut.
Profgen-cli unterstützt die Profilkompilierung, ‑Introspection und ‑Transpilierung von ART-Profilen, damit sie unabhängig von der Ziel-SDK-Version auf Android-Geräten installiert werden können.
Profgen-cli ist eine Befehlszeile, mit der die HRF eines Baseline-Profils in das kompilierte Format kompiliert wird. Die Befehlszeile ist auch im cmdline-tools
-Repository als Teil des Android SDK verfügbar.
Diese Funktionen sind in der studio-main
-Version verfügbar:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Kompakte Binärprofile mit Profgen-cli erstellen
Die mit Profgen-cli verfügbaren Befehle sind bin
, validate
und dumpProfile
. Mit profgen --help
können Sie die verfügbaren Befehle aufrufen:
➜ profgen --help
Usage: profgen options_list
Subcommands:
bin - Generate Binary Profile
validate - Validate Profile
dumpProfile - Dump a binary profile to a HRF
Options:
--help, -h -> Usage info
Verwenden Sie den Befehl bin
, um das kompakte Binärprofil zu generieren. Hier ein Beispiel für eine Aufrufabfolge:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Mit profgen bin options_list
kannst du die verfügbaren Optionen aufrufen:
Usage: profgen bin options_list
Arguments:
profile -> File path to Human Readable profile { String }
Options:
--apk, -a -> File path to apk (always required) { String }
--output, -o -> File path to generated binary profile (always required)
--map, -m -> File path to name obfuscation map { String }
--output-meta, -om -> File path to generated metadata output { String }
--profile-format, -pf [V0_1_0_P] -> The ART profile format version
{ Value should be one of [
v0_1_5_s, v0_1_0_p, v0_0_9_omr1, v0_0_5_o, v0_0_1_n
]
}
--help, -h -> Usage info
Das erste Argument ist der Pfad zum baseline-prof.txt
-HRF.
Profgen-cli benötigt außerdem den Pfad zum Release-Build des APK und eine Obfuscation Map, mit der das APK bei Verwendung von R8 oder Proguard verschleiert wird. So kann profgen
beim Erstellen des kompilierten Profils Quellsymbole im HRF in die entsprechenden verschleierten Namen umwandeln.
Da ART-Profilformate nicht vorwärts- oder rückwärtskompatibel sind, geben Sie ein Profilformat an, damit profgen
Profilmetadaten (profm
) einbettet, mit denen Sie bei Bedarf ein ART-Profilformat in ein anderes umwandeln können.
Profilformate und Plattformversionen
Bei der Auswahl eines Profilformats sind die folgenden Optionen verfügbar:
Profilformat | Plattform-Version | API-Ebene |
---|---|---|
v0_1_5_s | Android S+ | 31+ |
v0_1_0_p | Android P, Q und R | 28-30 |
v0_0_9_omr1 | Android O MR1 | 27 |
v0_0_5_o | Android O | 26 |
v0_0_1_n | Android N | 24-25 |
Kopieren Sie die Ausgabedateien baseline.prof
und baseline.profm
in den Ordner assets
oder dexopt
im APK.
Verschleierungskarten
Sie müssen die Verschleierungszuordnung nur angeben, wenn im HRF Quellsymbole verwendet werden. Wenn die HRF aus einem Release-Build generiert wird, der bereits verschleiert ist und keine Zuordnung erforderlich ist, können Sie diese Option ignorieren und die Ausgabe in den Ordner assets
oder dexopt
kopieren.
Traditionelle Installation von Baseline-Profilen
Baseline-Profile werden in der Regel auf eine von zwei Arten auf ein Gerät übertragen.
install-multiple
mit DexMetadata verwenden
Auf Geräten mit API 28 und höher lädt der Play-Client die APK- und DexMetadata-Nutzlast (DM) für eine installierte APK-Version herunter. Die DM enthält die Profilinformationen, die an den Paketmanager auf dem Gerät übergeben werden.
Das APK und das DM werden in einer einzigen Installationssitzung mit einem Befehl wie dem folgenden installiert:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Auf Geräten mit API-Level 29 und höher bietet die Jetpack ProfileInstaller-Bibliothek einen alternativen Mechanismus zum Installieren eines Profils, das in assets
oder dexopt
verpackt ist, nachdem das APK auf dem Gerät installiert wurde. ProfileInstaller
wird von ProfileInstallReceiver
oder direkt von der App aufgerufen.
Die ProfileInstaller-Bibliothek transkodiert das Profil basierend auf der SDK-Version des Zielgeräts und kopiert es in das Verzeichnis cur
auf dem Gerät (ein paketspezifisches Staging-Verzeichnis für ART-Profile auf dem Gerät).
Sobald das Gerät inaktiv ist, wird das Profil von einem Prozess namens bg-dexopt
auf dem Gerät übernommen.
Baseline-Profil per Sideload installieren
In diesem Abschnitt wird beschrieben, wie Sie ein Baseline-Profil anhand eines APK installieren.
Mit androidx.profileinstaller
streamen
Auf Geräten mit API 24 und höher können Sie einen Befehl zum Installieren des Profils senden:
# Broadcast the install profile command - moves binary profile from assets
# to a location where ART uses it for the next compile.
# When successful, the following command prints "1":
adb shell am broadcast \
-a androidx.profileinstaller.action.INSTALL_PROFILE \
<pkg>/androidx.profileinstaller.ProfileInstallReceiver
# Kill the process
am force-stop <pkg>
# Compile the package based on profile
adb shell cmd package compile -f -m speed-profile <pkg>
ProfileInstaller ist in den meisten APKs mit Baseline-Profilen nicht vorhanden, was etwa 77.000 von 450.000 Apps bei Google Play entspricht. Es ist jedoch in praktisch jeder APK vorhanden, die Compose verwendet. Das liegt daran, dass Bibliotheken Profile bereitstellen können, ohne eine Abhängigkeit von ProfileInstaller anzugeben. Das Hinzufügen einer Abhängigkeit in jeder Bibliothek mit einem Profil gilt ab Jetpack.
install-multiple
mit profgen oder DexMetaData verwenden
Auf Geräten mit API 28 und höher können Sie ein Baseline-Profil per Sideload installieren, ohne dass die ProfileInstaller-Bibliothek in der App vorhanden sein muss.
Verwenden Sie dazu Profgen-cli:
profgen extractProfile \
--apk app-release.apk \
--output-dex-metadata app-release.dm \
--profile-format V0_1_5_S # Select based on device and the preceding table.
# Install APK and the profile together
adb install-multiple appname-release.apk appname-release.dm
Führen Sie die Schritte zum Extrahieren des Profils einmal pro APK aus, um APK-Splits zu unterstützen. Übergeben Sie bei der Installation jedes APK und die zugehörige .dm
-Datei. Achten Sie darauf, dass die Namen der APK- und .dm
-Dateien übereinstimmen:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Bestätigung
Ob das Profil richtig installiert ist, können Sie anhand der Schritte unter App-Verbesserungen manuell messen prüfen.
Inhalt eines Binärprofils dumpen
Wenn Sie den Inhalt einer kompakten Binärversion eines Baseline-Profils prüfen möchten, verwenden Sie die Option dumpProfile
der Profgen-CLI:
Usage: profgen dumpProfile options_list
Options:
--profile, -p -> File path to the binary profile (always required)
--apk, -a -> File path to apk (always required) { String }
--map, -m -> File path to name obfuscation map { String }
--strict, -s [true] -> Strict mode
--output, -o -> File path for the HRF (always required) { String }
--help, -h -> Usage info
dumpProfile
benötigt das APK, da in der kompakten Binärdarstellung nur DEX-Abweichungen gespeichert werden. Daher sind diese erforderlich, um Klassen- und Methodennamen zu rekonstruieren.
Der strenge Modus ist standardmäßig aktiviert. Dabei wird eine Kompatibilitätsprüfung des Profils mit den DEX-Dateien im APK durchgeführt. Wenn Sie versuchen, Profile zu debuggen, die mit einem anderen Tool generiert wurden, kann es zu Kompatibilitätsfehlern kommen, die verhindern, dass Sie einen Dump zur Untersuchung erstellen können. In solchen Fällen können Sie den strengen Modus mit --strict false
deaktivieren. In den meisten Fällen sollten Sie den strengen Modus jedoch aktiviert lassen.
Eine Verschlüsselungskarte ist optional. Wenn Sie eine solche Karte angeben, können Sie verschleierte Symbole leichter in ihre visuell lesbaren Versionen umwandeln.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Best Practices für die SQLite-Leistung
- Baseline-Profile {:#baseline-profiles}
- Hängende Teil-Wakelocks