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. Es ist jedoch möglich, Profilregeln in Ihrer App manuell zu erstellen und zu messen.
Profilregeln manuell definieren
Sie können Profilregeln manuell in einer App oder einem Bibliotheksmodul definieren, indem Sie eine Datei mit dem Namen baseline-prof.txt
im Verzeichnis src/main
erstellen. Das 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 den Abgleich von Methoden oder Klassen in der App oder Bibliothek dar, die optimiert werden müssen.
Die Syntax für diese Regeln ist eine Obermenge des menschenlesbaren ART-Profilformats (Human-Readable Format, 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 Schreiben von Regeln zu vereinfachen.
Das folgende Beispiel zeigt einige Baseline Profile-Regeln, 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 Compiler Explorer-Beispielprojekt zu ändern. Compiler Explorer unterstützt nur das für Menschen lesbare ART-Profilformat (Human-Readable Format, HRF). Platzhalter werden daher nicht unterstützt.
Regelsyntax
Diese Regeln können entweder auf Methoden oder auf Klassen ausgerichtet sein:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Für eine Klassenregel gilt das folgende Muster:
[CLASS_DESCRIPTOR]
Eine detaillierte Beschreibung finden Sie in der folgenden Tabelle:
Syntax | Beschreibung |
---|---|
FLAGS |
Stellt ein 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 viele Male aufgerufen. Eine Methode mit dem Flag S ist eine Methode, die beim Start aufgerufen wird. Eine Methode mit dem Flag P wird nach dem Start aufgerufen. Eine in dieser Datei vorhandene Klasse weist darauf hin, 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 Zielmethode. androidx.compose.runtime.SlotTable hat beispielsweise den Deskriptor Landroidx/compose/runtime/SlotTable; . Gemäß dem Dalvik Executable (DEX)-Format wird hier ein „L“ vorangestellt. |
METHOD_SIGNATURE |
Signatur der Methode, einschließlich Name, Parametertypen und Rückgabetypen der Methode. Beispiel:// LayoutNode.kt fun isPlaced():Boolean { // ... } on LayoutNode hat die Signatur isPlaced()Z . |
Diese Muster können Platzhalter enthalten, damit eine einzelne Regel mehrere Methoden oder Klassen umfasst. Wenn Sie in Android Studio Unterstützung beim Schreiben von Regeln in der entsprechenden Syntax benötigen, können Sie das Android Baseline Profiles-Plug-in verwenden.
Eine Beispielregel mit Platzhaltern könnte so aussehen:
HSPLandroidx/compose/ui/layout/**->**(**)**
Unterstützte Typen in Baseline-Profilregeln
Baseline Profile-Regeln unterstützen die folgenden Typen. Weitere Informationen zu diesen Typen finden Sie unter Dalvik Executable (DEX).
Zeichen | Eingeben | Beschreibung |
---|---|---|
B |
Byte | Signiertes Byte |
C |
char | Unicode-Zeichen-Codepoint, codiert in UTF-16 |
D |
Doppelt | Gleitkommawert mit doppelter Genauigkeit |
F |
float | Gleitkommawert mit einfacher Genauigkeit |
I |
int | Ganzzahl |
J |
long | Lange Ganzzahl |
S |
kurz | Signiertes Short |
V |
void | Stornieren |
Z |
Boolesch | Richtig oder falsch? |
L (Klassenname) |
Referenz | Eine Instanz eines Klassennamens |
Außerdem können in Bibliotheken Regeln definiert werden, die in AAR-Artefakten enthalten sind. Wenn Sie ein APK erstellen, das diese Artefakte enthält, werden die Regeln zusammengeführt – ähnlich wie beim Zusammenführen von Manifesten – und in ein kompaktes binäres ART-Profil kompiliert, das spezifisch für das APK ist.
ART verwendet dieses Profil, wenn das APK auf Geräten verwendet wird, um bei der Installation unter Android 9 (API-Level 28) oder Android 7 (API-Level 24) mit ProfileInstaller
eine bestimmte Teilmenge 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 Ihrer kritischen User Journeys erstellen. Wir empfehlen zwar, Macrobenchmarks zu verwenden, aber das ist möglicherweise nicht immer möglich. Wenn Sie beispielsweise ein Build-System verwenden, das nicht auf Gradle basiert, können Sie das Baseline Profile Gradle-Plug-in nicht verwenden. In solchen Fällen können Sie Baseline Profile-Regeln manuell erfassen. Das ist viel einfacher, wenn Sie ein Gerät oder einen Emulator mit API 34 und höher verwenden. Das ist zwar auch mit niedrigeren API-Levels möglich, erfordert aber Root-Zugriff und die Verwendung eines Emulators, auf dem ein AOSP-Image ausgeführt wird. Sie können Regeln direkt so erfassen:
- Installieren Sie eine Releaseversion Ihrer App auf einem Testgerät. Der App-Build-Typ darf nicht R8-optimiert sein und darf nicht debugfähig sein, damit ein Profil erfasst werden kann, das vom Build-System verwendet werden kann.
- Deaktivieren Sie die Profilinstallation und beenden Sie die App.
Wenn Ihr APK von der Jetpack-Bibliothek Profile Installer abhängig ist, wird beim ersten Start Ihres APK ein Profil erstellt. Dies kann den Prozess der Profilerstellung beeinträchtigen. Deaktivieren Sie die Funktion daher mit dem folgenden Befehl:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
Setzen Sie die App-Kompilierung zurück und löschen Sie alle Profile.
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
Führen Sie die App aus und durchlaufen Sie manuell die kritischen User Journeys, für die Sie ein Profil erfassen möchten.
Warten Sie mindestens fünf Sekunden, damit sich die Profile stabilisieren können.
Führen Sie die Speicheraktion aus und warten Sie, bis das Speichern abgeschlossen ist. Wenn Ihr APK von der Jetpack Profile Installer-Bibliothek abhängig ist, verwenden Sie diese, um die Profile zu exportieren:
Wenn Sie Profile Installer nicht verwenden, sichern Sie die Profile manuell auf einem Emulator mit dem folgenden Befehl:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_PROFILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver sleep 1 # wait 1 second adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME sleep 1 # wait 1 second adb shell am force-stop $PACKAGE_NAME
Konvertieren Sie die generierten binären Profile 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 unter folgendem Pfad:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Speicherort der APK ermitteln:
adb root adb shell pm path $PACKAGE_NAME
Conversion durchführen:
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
Verwenden Sie
adb
, um das gesicherte Profil vom Gerät abzurufen: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. Beim nächsten Build der App ist das Baseline-Profil enthalten. Prüfen Sie dies anhand der Schritte unter Installationsprobleme.
App-Verbesserungen manuell messen
Wir empfehlen dringend, Verbesserungen an der App durch Benchmarking zu messen. Wenn Sie Verbesserungen jedoch manuell messen möchten, können Sie damit beginnen, den unoptimierten App-Start als Referenz zu 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"
Als Nächstes laden Sie das Baseline-Profil per Sideloading.
# 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
In der Ausgabe muss angegeben werden, 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 App-Startleistung jetzt wie gewohnt messen, ohne den kompilierten Status zurückzusetzen. Achten Sie darauf, dass Sie den kompilierten Status für das Paket nicht zurücksetzen.
# 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ären Version eines Baseline-Profils macht.
Profgen-cli unterstützt die Profilkompilierung, die Introspektion und das Transpilieren von ART-Profilen, damit sie unabhängig von der Ziel-SDK-Version auf Android-Geräten installiert werden können.
Profgen-cli ist eine CLI, die das HRF eines Baseline-Profils in das kompilierte Format kompiliert. Die Befehlszeile ist auch im cmdline-tools
-Repository als Teil des Android SDK enthalten.
Die folgenden Funktionen sind im studio-main
-Branch verfügbar:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Kompakte binäre Profile mit Profgen-cli erstellen
Die mit Profgen-cli verfügbaren Befehle sind bin
, validate
und dumpProfile
. Verwenden Sie profgen --help
, um die verfügbaren Befehle aufzurufen:
➜ 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äre Profil zu generieren. Hier ein Beispiel für einen Aufruf:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Verwenden Sie profgen bin options_list
, um die verfügbaren Optionen aufzurufen:
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 stellt den Pfad zur baseline-prof.txt
-HRF dar.
Für profgen-cli ist außerdem der Pfad zum Release-Build des APK und eine Verschleierungszuordnung erforderlich, die zum Verschleiern des APK verwendet wird, wenn R8 oder Proguard verwendet wird. So kann profgen
Quellsymbole im HRF beim Erstellen des kompilierten Profils in die entsprechenden verschleierten Namen übersetzen.
Da ART-Profilformate nicht vorwärts- oder rückwärtskompatibel sind, müssen Sie ein Profilformat angeben, damit profgen
Profilmetadaten (profm
) verpackt, die Sie bei Bedarf zum Transcodieren eines ART-Profilformats in ein anderes verwenden können.
Profilformate und Plattformversionen
Folgende Optionen stehen zur Verfügung, wenn Sie ein Profilformat auswählen:
Profilformat | Plattform-Version | API-Ebene |
---|---|---|
v0_1_5_s | Android S oder höher | 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
in der APK.
Verschleierungskarten
Sie müssen die Verschleierungstabelle 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 Ausgaben in den Ordner assets
oder dexopt
kopieren.
Traditionelle Installation von Baseline-Profilen
Baseline-Profile werden normalerweise auf 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 das APK und die DexMetadata-Nutzlast (DM) für eine APK-Version herunter, die installiert wird. Der DM enthält die Profilinformationen, die auf dem Gerät an den Paketmanager übergeben werden.
Das APK und das Geräte-Modell werden im Rahmen einer einzelnen Installationssitzung installiert, z. B. mit folgendem Befehl:
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 das Profil in das Verzeichnis cur
auf dem Gerät (ein paketbezogenes 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 abgerufen.
Baseline-Profil querladen
In diesem Abschnitt wird beschrieben, wie Sie ein Baseline-Profil anhand einer APK-Datei installieren.
Mit androidx.profileinstaller
übertragen
Auf Geräten mit API 24 und höher können Sie einen Broadcast-Befehl senden, um das Profil zu installieren:
# 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 Profiles nicht vorhanden. Das betrifft etwa 77.000 von 450.000 Apps bei Google Play. Allerdings ist ProfileInstaller in praktisch jedem APK vorhanden, in dem Compose verwendet wird. Das liegt daran, dass Bibliotheken Profile bereitstellen können, ohne eine Abhängigkeit von ProfileInstaller zu deklarieren. Ab Jetpack wird in jeder Bibliothek mit einem Profil eine Abhängigkeit hinzugefügt.
install-multiple
mit profgen oder DexMetaData verwenden
Auf Geräten mit API 28 und höher können Sie ein Baseline-Profil per Sideloading 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
Wenn Sie APK-Splits unterstützen möchten, führen Sie die vorherigen Schritte zum Extrahieren des Profils einmal pro APK aus. Übergeben Sie bei der Installation jedes APK und die zugehörige .dm
-Datei. Achten Sie darauf, dass die Namen des APK und der .dm
-Datei übereinstimmen:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Bestätigung
So prüfen Sie, ob das Profil richtig installiert ist: App-Verbesserungen manuell messen
Inhalte eines binären Profils ausgeben
Wenn Sie den Inhalt einer kompakten binären Version eines Baseline-Profils untersuchen 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ären Darstellung nur DEX-Offsets gespeichert werden. Daher sind sie erforderlich, um Klassen- und Methodennamen zu rekonstruieren.
Der strenge Modus ist standardmäßig aktiviert. Dabei wird ein Kompatibilitätscheck des Profils mit den DEX-Dateien im APK durchgeführt. Wenn Sie versuchen, Profile zu debuggen, die von einem anderen Tool generiert wurden, können Kompatibilitätsfehler auftreten, die verhindern, dass Sie die Profile zur Untersuchung sichern 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 Verschleierungszuordnung ist optional. Wenn sie angegeben wird, hilft sie, verschleierte Symbole zur besseren Lesbarkeit neu zuzuordnen.
Empfehlungen für dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Best Practices für die SQLite-Leistung
- Baseline-Profile {:#baseline-profiles}
- Hängende Teil-Wakelocks