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 Anwendung manuell zu erstellen und zu messen.
Profilregeln manuell definieren
Sie können Profilregeln manuell in einer Anwendung oder einem Bibliotheksmodul definieren. Dazu erstellen Sie eine Datei namens baseline-prof.txt
im Verzeichnis src/main
. Dies ist der Ordner, der auch die Datei AndroidManifest.xml
enthält.
In der Datei ist eine Regel pro Zeile angegeben. Jede Regel stellt ein Muster für Abgleichmethoden oder Klassen in der App oder Bibliothek dar, das optimiert werden muss.
Die Syntax für diese Regeln ist eine Obermenge des von Menschen lesbaren 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 jedoch die Verwendung von Platzhaltern, um das Schreiben von Regeln zu vereinfachen.
Das folgende Beispiel zeigt einige Baseline-Profilregeln, die in der Jetpack Composer-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;
Regelsyntax
Für die Ausrichtung auf Methoden oder Klassen gibt es zwei Arten dieser Regeln:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Eine Klassenregel verwendet das folgende Muster:
[CLASS_DESCRIPTOR]
Eine ausführliche 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 gibt an, dass es sich um eine „heiße“ Methode handelt, die während der Lebensdauer der App mehrmals aufgerufen wird. Eine Methode mit dem Flag S gibt an, dass es sich um eine Methode handelt, die beim Start aufgerufen wird. Eine Methode mit dem Flag P gibt an, dass es sich um eine Methode handelt, die nach dem Start aufgerufen wird. Eine in dieser Datei vorhandene Klasse gibt an, dass sie beim Start verwendet wird und im Heap zugewiesen werden muss, um Kosten für das Laden der Klasse zu vermeiden. Der ART-Compiler verwendet verschiedene Optimierungsstrategien, z. B. die AOT-Kompilierung dieser Methoden und die Layoutoptimierung in der generierten AOT-Datei. |
CLASS_DESCRIPTOR |
Deskriptor für die Klasse der Zielmethode. Beispielsweise hat androidx.compose.runtime.SlotTable den Deskriptor Landroidx/compose/runtime/SlotTable; . L wird hier im 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 umfasst. Eine Anleitung zum Schreiben mit Regelsyntax in Android Studio finden Sie im Plug-in Android Baseline Profiles (Android-Baseline-Profile).
Eine Platzhalterregel könnte beispielsweise so aussehen:
HSPLandroidx/compose/ui/layout/**->**(**)**
Unterstützte Typen in Regeln für das Referenzprofil
Regeln für Referenzprofile unterstützen die folgenden Typen. Weitere Informationen zu diesen Typen finden Sie im Dalvik Executable-Format (DEX).
Zeichen | Typ | Beschreibung |
---|---|---|
B |
Byte | Signiertes Byte |
C |
Zeichen | Unicode-Zeichencodepunkt mit UTF-16-Codierung |
D |
Doppelt | Gleitkommawert mit doppelter Genauigkeit |
F |
schweben | Gleitkommawert mit einfacher Genauigkeit |
I |
int | Ganzzahl |
J |
lang | Lange Ganzzahl |
S |
kurz | Kurzes signiertes Element |
V |
void | Ungültig |
Z |
boolean | Richtig oder falsch? |
L (Kursname) |
Referenz | Instanz eines Klassennamens |
Außerdem können Bibliotheken Regeln definieren, die in AAR-Artefakte gepackt sind. Wenn du ein APK erstellst, das diese Artefakte enthält, werden die Regeln zusammengeführt – ähnlich wie beim Zusammenführen von Manifesten – und zu einem kompakten binären 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-Level 28) oder Android 7 (API-Level 24) bei Verwendung von ProfileInstaller
eine bestimmte Teilmenge der App zu kompilieren.
Referenzprofile manuell erfassen
Sie können manuell ein Baseline-Profil generieren, ohne die MacroBenchmark-Bibliothek einzurichten, und UI-Automatisierungen für Ihre kritischen Nutzerpfade erstellen. Auch wenn wir die Verwendung von Makro-Benchmarks empfehlen, ist dies nicht immer möglich. Wenn Sie beispielsweise ein Nicht-Gradle-Build-System 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. Dies ist viel einfacher, wenn Sie ein Gerät oder einen Emulator mit API 34 und höher verwenden. Auch wenn dies mit niedrigeren API-Ebenen immer noch möglich ist, ist dafür Root-Zugriff erforderlich. Außerdem müssen Sie einen Emulator verwenden, der ein AOSP-Image ausführt. So können Sie Regeln direkt erfassen:
- Installiere eine Release-Version deiner App auf einem Testgerät. Der Build-Typ der Anwendung muss für ein genaues Profil R8-optimiert und nicht Debug-fähig sein.
- Achten Sie darauf, dass die Profile nicht bereits kompiliert sind.
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 dein APK eine Abhängigkeit von der Jetpack-Bibliothek Profile Installer hat, startet die Bibliothek beim ersten Start des APK ein Profil. Dies kann den Prozess der Profilerstellung beeinträchtigen. Deaktivieren Sie ihn 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 gehen Sie manuell durch Ihre kritischen User Journeys, für die Sie ein Profil erstellen möchten.
- Fordere ART auf, die Profile auszuwerfen. Wenn Ihr APK eine Abhängigkeit von der Jetpack Profile Installer-Bibliothek hat, verwenden Sie diese zum Dump der Profile:
adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
Wenn Sie Profile Installer nicht verwenden, sichern Sie die Profile mit dem folgenden Befehl manuell in einem Emulator:adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME adb shell am force-stop $PACKAGE_NAME
- Warten Sie mindestens fünf Sekunden, bis die Profilerstellung abgeschlossen ist.
- 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
Feststellen, 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 am folgenden Speicherort:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
So ermitteln Sie den Speicherort des APK:
adb root adb shell pm path $PACKAGE_NAME
Führen Sie die Umwandlung durch:
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 Dumpprofil 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. Wenn Sie die Anwendung das nächste Mal erstellen, wird das Baseline-Profil eingefügt. Prüfen Sie dies anhand der Schritte unter Probleme bei der Installation.
App-Verbesserungen manuell messen
Wir empfehlen dringend, App-Verbesserungen durch Benchmarking zu messen. Wenn Sie Verbesserungen jedoch manuell messen möchten, können Sie damit beginnen, den nicht optimierten Anwendungsstart zu Referenzzwecken 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"
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 überprü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 ist:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Jetzt können Sie die Startleistung von Anwendungen wie zuvor 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 Vermittlung
In diesem Abschnitt wird beschrieben, wie das Tool profgen eine kompakte Binärversion eines Baseline-Profils erstellt.
Profgen-cli hilft bei der Profilkompilierung, Selbstprüfung und Übersetzung von ART-Profilen, sodass sie unabhängig von der SDK-Zielversion auf Android-Geräten installiert werden können.
Profgen-cli ist eine Befehlszeile, die die HRF eines Baseline-Profils in sein kompiliertes Format kompiliert. Die Befehlszeile wird als Teil des Android SDK auch im cmdline-tools
-Repository enthalten.
Diese Features sind im studio-main
-Zweig verfügbar:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Kompakte Binärprofile mit Profgen-cli erstellen
In Profgen-cli sind die Befehle bin
, validate
und dumpProfile
verfügbar. 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 Beispielaufruf:
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
können Sie 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 stellt den Pfad zum baseline-prof.txt
-HRF dar.
Außerdem benötigt Profgen-cli den Pfad zum Release-Build des APK und eine Verschleierungskarte, mit der das APK bei Verwendung von R8 oder Proguard verschleiert wird. Auf diese Weise kann profgen
beim Erstellen des kompilierten Profils Quellsymbole im HRF in die entsprechenden verschleierten Namen übersetzen.
Da ART-Profileformate nicht vorwärts- oder abwärtskompatibel sind, solltest du ein Profilformat angeben, damit profgen
Profilmetadaten (profm
) verpackt, die du bei Bedarf zum Transcodieren eines ART-Profilformats in ein anderes verwenden kannst.
Profilformate und Plattformversionen
Die folgenden Optionen sind bei der Auswahl eines Profilformats verfügbar:
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 (Version 0_0_9_Omr1) | Android O MR1 | 27 |
v0_0_5_o | Android O | 26 |
v0_0_1_n | Android N | 24-25 |
Kopiere die Ausgabedateien baseline.prof
und baseline.profm
in den Ordner assets
oder dexopt
des APK.
Verschleierungskarten
Sie müssen die Verschleierungskarte nur dann bereitstellen, wenn das HRF Quellsymbole verwendet. Wenn die HRF aus einem bereits verschleierten Release-Build generiert wird und keine Zuordnung erforderlich ist, können Sie diese Option ignorieren und die Ausgaben in den Ordner assets
oder dexopt
kopieren.
Herkömmliche Installation von Baseline-Profilen
Referenzprofile werden normalerweise auf eine von zwei Arten an ein Gerät gesendet.
install-multiple
mit DexMetadata verwenden
Auf Geräten mit API 28 und höher lädt der Play-Client die APK- und DesMetadata- (DM)-Nutzlast für eine APK-Version herunter, die installiert wird. Die DM enthält die Profilinformationen, die auf dem Gerät an den Paketmanager übergeben werden.
Das APK und die DM werden im Rahmen einer einzelnen Installationssitzung installiert. Dies geschieht in etwa so:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Auf Geräten mit API-Level 29 und höher bietet die Bibliothek Jetpack ProfileInstaller einen alternativen Mechanismus zur Installation eines in assets
oder dexopt
gepackten Profils, nachdem das APK auf dem Gerät installiert wurde. ProfileInstaller
wird von ProfileInstallReceiver
oder direkt von der Anwendung aufgerufen.
Die ProfileInstaller-Bibliothek transcodiert 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.
Referenzprofil per Sideload übertragen
In diesem Abschnitt wird beschrieben, wie ein Baseline-Profil für ein APK installiert wird.
Nachricht an alle mit androidx.profileinstaller
Auf Geräten mit API 24 und höher können Sie einen Befehl zur Installation 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. Diese befindet sich in etwa 77.000 von 450.000 Apps bei Google Play, obwohl es praktisch in jedem APK mit Compose vorhanden ist. Das liegt daran, dass Bibliotheken Profile bereitstellen können, ohne eine Abhängigkeit von ProfileInstaller zu deklarieren. Das Hinzufügen einer Abhängigkeit in jeder Bibliothek mit einem Profil gilt beginnend mit 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 übertragen, ohne dass in der App die ProfileInstaller-Bibliothek vorhanden ist.
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ühre die vorherigen Schritte zum Extrahieren des Profils einmal pro APK aus, um APK-Aufteilungen zu unterstützen. Übergib bei der Installation jedes APK und die zugehörige .dm
-Datei und achte darauf, dass die Namen des APK und der .dm
übereinstimmen:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Bestätigung
Mit den Schritten unter App-Verbesserungen manuell messen können Sie prüfen, ob das Profil korrekt installiert ist.
Inhalt eines Binärprofils auslesen
Verwenden Sie die Profgen-cli-Option dumpProfile
, um den Inhalt einer kompakten Binärversion eines Referenzprofils selbst zu prüfen:
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 die kompakte binäre Darstellung nur DEX-Offsets speichert und sie daher benötigt, um Klassen- und Methodennamen zu rekonstruieren.
Der strikte Modus ist standardmäßig aktiviert. Dadurch wird eine Kompatibilitätsprüfung des Profils mit den DEX-Dateien im APK durchgeführt. Wenn Sie Fehler in Profilen beheben, die von einem anderen Tool generiert wurden, treten möglicherweise Kompatibilitätsfehler auf, die verhindern, dass Sie einen Dump für die Prüfung erstellen können. In solchen Fällen können Sie den strikten Modus mit --strict false
deaktivieren. In den meisten Fällen sollten Sie den strikten Modus jedoch aktiviert lassen.
Eine Verschleierungskarte ist optional. Wenn sie bereitgestellt wird, hilft sie dabei, verschleierte Symbole der einfacheren Verwendung für Menschen lesbar zu machen.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Best Practices für SQLite-Leistung
- Baseline-Profile {:#baseline-profiles}
- Hängende Teil-Wakelocks