Zdecydowanie zalecamy zautomatyzowanie generowania reguł profilu za pomocą biblioteki Jetpack Macrobenchmark aby zmniejszyć nakład pracy ręcznej i zwiększyć ogólną skalowalność. Możesz jednak ręcznie tworzyć i mierzyć reguły profilu w swojej aplikacji.
Ręczne definiowanie reguł profilu
Reguły profilu możesz zdefiniować ręcznie w aplikacji lub module biblioteki, tworząc plik o nazwie baseline-prof.txt znajdujący się w katalogu src/main. Jest to ten sam folder, który zawiera plik AndroidManifest.xml.
Plik określa 1 regułę w wierszu. Każda reguła reprezentuje wzorzec dopasowywania metod lub klas w aplikacji lub bibliotece, które wymagają optymalizacji.
Składnia tych reguł jest nadzbiorem formatu profilu ART zrozumiałego dla człowieka (HRF) podczas używania polecenia adb shell profman --dump-classes-and-methods. Składnia jest podobna do składni deskryptorów i
sygnatur, ale umożliwia używanie symboli wieloznacznych, co upraszcza proces pisania reguł.
Ten przykład pokazuje kilka reguł profilu podstawowego zawartych w bibliotece Jetpack Compose:
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;
Możesz spróbować zmodyfikować reguły profilu w tym przykładowym projekcie Compiler Explorer. Pamiętaj, że Compiler Explorer obsługuje tylko format profilu ART zrozumiałego dla człowieka (HRF), więc symbole wieloznaczne nie są obsługiwane.
Składnia reguł
Te reguły przyjmują jedną z 2 postaci, aby kierować na metody lub klasy:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Reguła klasy używa tego wzorca:
[CLASS_DESCRIPTOR]
Szczegółowy opis znajdziesz w tej tabeli:
| Składnia | Opis |
|---|---|
FLAGS |
Reprezentuje co najmniej 1 znak: H, S lub P, aby wskazać, czy ta metoda musi być oznaczona jako Hot, Startup lub Post Startup w zależności od typu uruchomienia. Metoda z flagą H jest metodą „gorącą”, co oznacza, że jest wywoływana wiele razy w trakcie działania aplikacji. Metoda z flagą S jest metodą wywoływaną podczas uruchamiania. Metoda z flagą P jest metodą wywoływaną po uruchomieniu. Klasa obecna w tym pliku wskazuje, że jest używana podczas uruchamiania i musi być wstępnie przydzielona w stercie, aby uniknąć kosztów ładowania klasy. Kompilator ART stosuje różne strategie optymalizacji, takie jak kompilacja AOT tych metod i optymalizacja układu w wygenerowanym pliku AOT. |
CLASS_DESCRIPTOR |
Deskryptor klasy metody docelowej. Na przykład androidx.compose.runtime.SlotTable ma deskryptor Landroidx/compose/runtime/SlotTable;. W tym przypadku przedrostek L jest dodawany zgodnie z formatem Dalvik Executable (DEX). |
METHOD_SIGNATURE |
Sygnatura metody, w tym jej nazwa, typy parametrów i typy zwracane. Przykład:// LayoutNode.kt fun isPlaced():Boolean { // ...} w przypadku LayoutNode ma sygnaturę isPlaced()Z. |
Te wzorce mogą zawierać symbole wieloznaczne, dzięki czemu jedna reguła może obejmować wiele metod lub klas. Aby uzyskać pomoc podczas pisania składni reguł w Android Studio, zapoznaj się z wtyczką Android Baseline Profiles.
Przykład reguły z symbolem wieloznacznym:
HSPLandroidx/compose/ui/layout/**->**(**)**
Obsługiwane typy w regułach profilu podstawowego
Reguły profilu podstawowego obsługują te typy. Więcej informacji o tych typach, znajdziesz w artykule Format Dalvik Executable (DEX) format.
| Znak | Typ | Opis |
|---|---|---|
B |
bajt | Bajt ze znakiem |
C |
char | Punkt kodowy Unicode zakodowany w UTF-16 |
D |
liczba zmiennoprzecinkowa | Wartość zmiennoprzecinkowa podwójnej precyzji |
F |
liczba zmiennoprzecinkowa | Wartość zmiennoprzecinkowa pojedynczej precyzji |
I |
int | Liczba całkowita |
J |
długi | Długa liczba całkowita |
S |
krótki | Krótka liczba ze znakiem |
V |
void | Void |
Z |
Wartość logiczna | Prawda czy fałsz? |
L (nazwa zajęć) |
odniesienie | Instancja nazwy klasy |
Biblioteki mogą też definiować reguły, które są spakowane w artefakty AAR. Gdy tworzysz plik APK, aby uwzględnić te artefakty, reguły są łączone – podobnie jak w przypadku łączenia manifestów – i kompilowane do kompaktowego binarnego profilu ART, który jest specyficzny dla pliku APK.
ART wykorzystuje ten profil, gdy plik APK jest używany na urządzeniach do kompilowania AOT
określonego podzbioru aplikacji podczas instalacji na Androidzie 9 (poziom interfejsu API 28),
lub Androidzie 7 (poziom interfejsu API 24) w przypadku używania
ProfileInstaller.
Ręczne zbieranie profili podstawowych
Możesz ręcznie wygenerować profil podstawowy bez konfigurowania biblioteki Macrobenchmark i tworzyć automatyzacje interfejsu użytkownika w przypadku najważniejszych ścieżek użytkownika. Chociaż zalecamy używanie biblioteki Macrobenchmark, nie zawsze jest to możliwe. Jeśli na przykład używasz systemu kompilacji innego niż Gradle, nie możesz używać wtyczki Gradle profilu podstawowego. W takich przypadkach możesz ręcznie zbierać reguły profilu podstawowego. Jest to znacznie łatwiejsze, jeśli używasz urządzenia lub emulatora z interfejsem API w wersji 34 lub nowszej. Chociaż jest to nadal możliwe w przypadku niższych poziomów interfejsu API, wymaga dostępu do roota i użycia emulatora z obrazem AOSP. Reguły możesz zbierać bezpośrednio, wykonując te czynności:
- Zainstaluj wersję do publikacji swojej aplikacji na urządzeniu testowym. Rodzaj kompilacji aplikacji nie może być zoptymalizowany pod kątem R8 i nie może być z możliwością debugowania, aby można było przechwycić profil, który może być używany przez system kompilacji.
- Wyłącz instalację profilu i zamknij aplikację.
Jeśli plik APK jest zależny od biblioteki Jetpack Profile Installer, biblioteka uruchomi profil przy pierwszym uruchomieniu pliku APK. Może to zakłócić proces generowania profilu, więc wyłącz go za pomocą tego polecenia:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
Zresetuj kompilację aplikacji i wyczyść wszystkie profile.
Interfejs API w wersji 34 lub nowszej
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
Interfejs API w wersji 33 lub starszej
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Uruchom aplikację i ręcznie przejdź przez najważniejsze ścieżki użytkownika, dla których chcesz zebrać profil.
Odczekaj co najmniej 5 sekund, aby profile się ustabilizowały.
Wykonaj działanie zapisu i poczekaj na jego zakończenie. Jeśli plik APK jest zależny od biblioteki Jetpack Profile Installer, użyj jej do zrzucenia profili:
Jeśli nie używasz Profile Installer, zrzuć profile ręcznie w emulatorze za pomocą tego polecenia: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
Przekonwertuj wygenerowane profile binarne na tekst:
Interfejs API w wersji 34 lub nowszej
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
Interfejs API w wersji 33 lub starszej
Sprawdź, czy został utworzony profil odniesienia czy bieżący. Profil odniesienia znajduje się w tej lokalizacji:
/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Bieżący profil znajduje się w tej lokalizacji:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Określ lokalizację pliku APK:
adb root adb shell pm path $PACKAGE_NAME
Wykonaj konwersję:
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
Użyj
adb, aby pobrać z urządzenia zrzucony profil:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Spowoduje to pobranie wygenerowanych reguł profilu i zainstalowanie ich w module aplikacji. Przy następnej kompilacji aplikacji zostanie uwzględniony profil podstawowy. Sprawdź to wykonując czynności opisane w sekcji Problemy z instalacją.
Ręczne mierzenie ulepszeń aplikacji
Zdecydowanie zalecamy mierzenie ulepszeń aplikacji za pomocą testów porównawczych. Jeśli jednak chcesz mierzyć ulepszenia ręcznie, możesz zacząć od pomiaru uruchomienia nieoptymalizowanej aplikacji.
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"
Następnie wczytaj profil podstawowy.
# 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
Aby sprawdzić, czy pakiet został zoptymalizowany podczas instalacji, uruchom to polecenie:
# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAMEDane wyjściowe muszą wskazywać, że pakiet został skompilowany:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Teraz możesz mierzyć wydajność uruchamiania aplikacji tak jak wcześniej, ale bez resetowania stanu skompilowanego. Upewnij się, że nie resetujesz stanu skompilowanego pakietu.
# 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"
Profile podstawowe i profgen
W tej sekcji opisujemy, co robi narzędzie profgen podczas tworzenia kompaktowej wersji binarnej profilu podstawowego.
Profgen-cli pomaga w kompilowaniu, introspekcji i transpilacji profili ART, dzięki czemu można je instalować na urządzeniach z Androidem niezależnie od docelowej wersji pakietu SDK.
Profgen-cli to interfejs wiersza poleceń, który kompiluje HRF profilu podstawowego do jego skompilowanego formatu. Interfejs wiersza poleceń jest też dostępny w
repozytorium cmdline-tools jako część pakietu Android
SDK.
Te funkcje są dostępne w gałęzi studio-main:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Kompilowanie kompaktowych profili binarnych za pomocą Profgen-cli
Polecenia dostępne w Profgen-cli to bin, validate i dumpProfile. Aby zobaczyć dostępne polecenia, użyj polecenia profgen --help:
➜ 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
Użyj polecenia bin, aby wygenerować kompaktowy profil binarny. Oto przykład wywołania:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Aby zobaczyć dostępne opcje, użyj polecenia profgen bin options_list:
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
Pierwszy argument reprezentuje ścieżkę do pliku HRF baseline-prof.txt.
Profgen-cli potrzebuje też ścieżki do kompilacji do publikacji pliku APK i
mapy zaciemniania, która służy do zaciemniania pliku APK podczas
używania R8 lub Proguard. Dzięki temu profgen może tłumaczyć symbole źródłowe w HRF na odpowiadające im zaciemnione nazwy podczas tworzenia skompilowanego profilu.
Ponieważ formaty profili ART nie są kompatybilne wstecz ani w przód, podaj format profilu, aby profgen mógł spakować metadane profilu (profm), których możesz użyć do transkodowania jednego formatu profilu ART na inny, gdy jest to wymagane.
Formaty profili i wersje platformy
Podczas wybierania formatu profilu dostępne są te opcje:
| Format profilu | Wersja platformy | Poziom API |
|---|---|---|
| v0_1_5_s | Android S lub nowszy | ponad 31 |
| v0_1_0_p | Android P, Q i 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 |
Skopiuj pliki wyjściowe baseline.prof i baseline.profm do folderu
assets lub dexopt w pliku APK.
Mapy zaciemniania
Mapę zaciemniania musisz podać tylko wtedy, gdy HRF używa symboli źródłowych. Jeśli HRF jest generowany na podstawie kompilacji do publikacji, która jest już zaciemniona, i nie jest wymagane mapowanie, możesz zignorować tę opcję i skopiować dane wyjściowe do folderu assets lub dexopt.
Tradycyjna instalacja profili podstawowych
Profile podstawowe są tradycyjnie dostarczane na urządzenie na 2 sposoby.
Używanie install-multiple z DexMetadata
Na urządzeniach z interfejsem API w wersji 28 lub nowszej klient Play pobiera plik APK i ładunek DexMetadata (DM) dla instalowanej wersji pliku APK. DM zawiera informacje o profilu, które są przekazywane do Menedżera pakietów na urządzeniu.
Plik APK i DM są instalowane w ramach jednej sesji instalacji za pomocą polecenia takiego jak:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Na urządzeniach z interfejsem API w wersji 29 lub nowszej biblioteka Jetpack
ProfileInstaller zapewnia alternatywny
mechanizm instalowania profilu spakowanego w assets lub dexopt po zainstalowaniu pliku APK
na urządzeniu. ProfileInstaller jest wywoływany przez
ProfileInstallReceiver lub bezpośrednio przez aplikację.
Biblioteka ProfileInstaller transkoduje profil na podstawie wersji pakietu SDK urządzenia docelowego i kopiuje profil do katalogu cur na urządzeniu (katalog tymczasowy specyficzny dla pakietu na potrzeby profili ART na urządzeniu).
Gdy urządzenie jest bezczynne, profil jest pobierany przez proces o nazwie bg-dexopt na urządzeniu.
Wczytywanie profilu podstawowego
W tej sekcji opisujemy, jak zainstalować profil podstawowy na podstawie pliku APK.
Przesyłanie za pomocą androidx.profileinstaller
Na urządzeniach z interfejsem API w wersji 24 lub nowszej możesz przesłać polecenie zainstalowania profilu:
# 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>
Biblioteka ProfileInstaller nie jest obecna w większości plików APK z profilami podstawowymi (czyli w około 77 tys. z 450 tys. aplikacji w Play), ale jest obecna w praktycznie każdym pliku APK korzystającym z Compose. Dzieje się tak, ponieważ biblioteki mogą udostępniać profile bez deklarowania zależności od ProfileInstaller. Dodawanie zależności w każdej bibliotece z profilem jest stosowane od Jetpack.
Używanie install-multiple z profgen lub DexMetadata
Na urządzeniach z interfejsem API w wersji 28 lub nowszej możesz wczytać profil podstawowy bez konieczności posiadania w aplikacji biblioteki ProfileInstaller.
Aby to zrobić, użyj 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
Aby obsługiwać podziały APK, wykonaj powyższe czynności wyodrębniania profilu raz na każdy plik APK. Podczas instalacji przekaż każdy plik APK i powiązany z nim plik .dm, upewniając się, że nazwy pliku APK i .dm są zgodne:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Weryfikacja
Aby sprawdzić, czy profil jest prawidłowo zainstalowany, możesz wykonać czynności opisane w sekcji Ręczne mierzenie ulepszeń aplikacji.
Zrzucanie zawartości profilu binarnego
Aby sprawdzić zawartość kompaktowej wersji binarnej profilu podstawowego, użyj opcji dumpProfile w 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 potrzebuje pliku APK, ponieważ kompaktowa reprezentacja binarna przechowuje tylko przesunięcia DEX, dlatego potrzebuje ich do rekonstrukcji nazw klas i metod.
Domyślnie włączony jest tryb ścisły, który sprawdza zgodność profilu z plikami DEX w pliku APK. Jeśli próbujesz debugować profile wygenerowane przez inne narzędzie, możesz napotkać błędy zgodności, które uniemożliwią zrzucenie profilu do analizy. W takich przypadkach możesz wyłączyć tryb ścisły za pomocą polecenia --strict false. W większości przypadków należy jednak pozostawić włączony tryb ścisły.
Mapa zaciemniania jest opcjonalna. Jeśli ją podasz, pomoże ona w ponownym mapowaniu zaciemnionych symboli na ich wersje zrozumiałe dla człowieka, co ułatwi korzystanie.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Sprawdzone metody dotyczące wydajności SQLite
- Profile podstawowe {:#baseline-profiles}
- Ciągłe częściowe blokady uśpienia