Zdecydowanie zalecamy zautomatyzowanie generowania reguł profilu za pomocą biblioteki Macrobenchmark w Jetpacku, aby zmniejszyć nakład pracy ręcznej i zwiększyć ogólną skalowalność. W aplikacji możesz jednak ręcznie tworzyć i mierzyć reguły profilu.
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
w katalogu src/main
. Jest to ten sam folder, który zawiera plik AndroidManifest.xml
.
Plik zawiera po 1 regułę na wiersz. Każda reguła reprezentuje wzór dopasowywania metod lub klas w aplikacji lub bibliotece, który wymaga optymalizacji.
Składnia tych reguł jest superzestawem czytelnego dla człowieka formatu profilu ART (HRF) w przypadku użycia adb shell profman --dump-classes-and-methods
. Składnia jest podobna do składni stosowanej w przypadku deskryptorów i podpisów, ale umożliwia używanie symboli wieloznacznych w celu uproszczenia procesu tworzenia reguł.
Ten przykład pokazuje kilka reguł profilu podstawowego dostępnych w bibliotece Compose w Jetpacku:
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 próbnym projekcie Compiler Explorer. Pamiętaj, że Compiler Explorer obsługuje tylko format profilu ART zrozumiały dla człowieka (HRF), więc znaki zastępcze nie są obsługiwane.
Składnia reguł
Te reguły mogą mieć jedną z 2 form, aby kierować się na metody lub klasy:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Reguła klasy używa tego wzoru:
[CLASS_DESCRIPTOR]
Szczegółowe informacje znajdziesz w tabeli poniżej:
Składnia | Opis |
---|---|
FLAGS |
Reprezentuje co najmniej jeden z znaków H , S i P , aby wskazać, czy ta metoda musi być oznaczona jako Hot , Startup czy Post Startup w zależności od typu uruchamiania. Metoda z flagą H oznacza, że jest to „gorąca” metoda, czyli jest wywoływana wiele razy w trakcie działania aplikacji. Metoda z flagą S oznacza, że jest to metoda wywoływana podczas uruchamiania. Metoda z flagą P wskazuje, że jest to metoda wywoływana po uruchomieniu. Klasa obecna w tym pliku wskazuje, że jest używana podczas uruchamiania i musi być wstępnie przydzielona w stogu, aby uniknąć kosztów wczytywania 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 docelowej metody. Na przykład androidx.compose.runtime.SlotTable ma deskryptor Landroidx/compose/runtime/SlotTable; . L jest dodawane na początku zgodnie z formatem Dalvik Executable (DEX). |
METHOD_SIGNATURE |
sygnaturę metody, w tym nazwę, typy parametrów i typy zwracane metody; Na przykład:// LayoutNode.kt fun isPlaced():Boolean { // ... } na LayoutNode ma podpis isPlaced()Z . |
Te wzorce mogą zawierać symbole wieloznaczne, aby jedna reguła obejmowała wiele metod lub klas. Aby uzyskać pomoc podczas pisania kodu z syntaksą reguł w Android Studio, skorzystaj z wtyczki Android Baseline Profiles.
Przykład reguły z symbolem wieloznaczeniowym może wyglądać tak:
HSPLandroidx/compose/ui/layout/**->**(**)**
Obsługiwane typy w regułach profilu podstawowego
Reguły profilu podstawowego obsługują te typy. Szczegółowe informacje o tych typach znajdziesz w artykule Format pliku wykonywalnego Dalvik (DEX).
Znak | Typ | Opis |
---|---|---|
B |
bajt | Bajt podpisany |
C |
char | Punkt kodowy znaku Unicode zakodowany w UTF-16 |
D |
podwójny | Wartość zmiennoprzecinkowa podwójnej precyzji |
F |
float | Wartość zmiennoprzecinkowa o pojedynczej precyzji |
I |
int | Liczba całkowita |
J |
długi | Długa liczba całkowita |
S |
krótki | Podpisany film Short |
V |
nieważne | Anulowanie |
Z |
wartość logiczna | Prawda czy fałsz? |
L (nazwa klasy) |
pliku referencyjnego | instancja nazwy klasy, |
Biblioteki mogą też definiować reguły, które są pakowane w elementy AAR. Gdy kompilujesz plik APK, aby zawierał te elementy, reguły są scalane (podobnie jak w przypadku scalania manifestu) i skompilowane w kompaktowy binarny profil ART, który jest specyficzny dla pliku APK.
Profil ten jest używany przez ART w przypadku plików APK na urządzeniach do kompilacji AOT określonego podzbioru aplikacji w momencie instalacji na Androidzie 9 (poziom interfejsu API 28) lub Androidzie 7 (poziom interfejsu API 24) podczas korzystania z ProfileInstaller
.
Ręczne zbieranie profili podstawowych
Możesz ręcznie wygenerować profil referencyjny bez konfigurowania biblioteki Macrobenchmark i utworzyć automatyzacje interfejsu użytkownika dotyczące kluczowych ścieżek użytkownika. Chociaż zalecamy korzystanie z testów porównawczych makro, 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 do profilu bazowego. W takich przypadkach możesz ręcznie zebrać zasady dotyczące profilu podstawowego. Jest to znacznie łatwiejsze, jeśli używasz urządzenia lub emulatora z poziomem interfejsu API 34 lub nowszym. Chociaż jest to nadal możliwe na niższych poziomach interfejsu API, wymaga dostępu roota i użycia emulatora z obrazem AOSP. Aby zebrać reguły bezpośrednio:
- Zainstaluj wersję aplikacji na urządzeniu testowym. Aby uzyskać dokładny profil, typ kompilacji aplikacji musi być zoptymalizowany pod kątem R8 i niemożliwy do debugowania.
- Upewnij się, że profile nie zostały już skompilowane.
Interfejs API 34 lub nowszy
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
Poziom 33 interfejsu API lub niższy
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Jeśli plik APK jest zależny od biblioteki Profile Installer z Jetpacka, biblioteka ta uruchamia profil przy pierwszym uruchomieniu pliku APK. Może to zakłócać proces generowania profilu, dlatego wyłącz go za pomocą tego polecenia:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
- Uruchom aplikację i ręcznie przejdź przez najważniejsze ścieżki użytkownika, których profil chcesz stworzyć.
- Poproś ART o wygenerowanie profili. Jeśli plik APK jest zależny od biblioteki Profile Installer z Jetpacka, użyj jej do zrzutu profili:
Jeśli nie używasz Profile Installer, wygeneruj profile ręcznie na emulatorze za pomocą tego polecenia:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME adb shell am force-stop $PACKAGE_NAME
- Zaczekaj co najmniej 5 sekund, aby umożliwić wygenerowanie profilu.
- Konwertuj wygenerowane profile binarne na tekst:
Interfejs API 34 lub nowszy
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
Poziom 33 interfejsu API lub niższy
Określ, czy został utworzony profil referencyjny czy bieżący. Profil referencyjny znajduje się w tym miejscu:
/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Bieżący profil znajduje się w tym miejscu:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Określ lokalizację pliku APK:
adb root adb shell pm path $PACKAGE_NAME
Przeprowadź 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
- Aby pobrać z urządzenia wygenerowany profil, użyj polecenia
adb
:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Spowoduje to pobranie wygenerowanych reguł profilu i ich zainstalowanie w module aplikacji. Gdy następnym razem skompilujesz aplikację, profil bazowy zostanie uwzględniony. Aby to sprawdzić, wykonaj czynności opisane w sekcji Problemy z instalacją.
Ręczne pomiary ulepszeń aplikacji
Zdecydowanie zalecamy pomiar ulepszeń aplikacji za pomocą porównań. Jeśli jednak chcesz mierzyć ulepszenia ręcznie, możesz zacząć od pomiaru czasu uruchamiania 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 prześlij 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_NAME
Dane wyjściowe muszą zawierać informację o skompilowaniu pakietu:
[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 skompilowanego stanu. Upewnij się, że nie zresetujesz skompilowanego stanu 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 opisano, co robi narzędzie profgen podczas kompilowania skompresowanej wersji binarnej profilu bazowego.
Narzędzie Profgen-cli ułatwia kompilowanie profili, analizowanie ich i transpilowanie profili ART, aby można je było 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 skompilowanego formatu. Interfejs wiersza poleceń jest też dostępny w repozytorium cmdline-tools
w ramach pakietu SDK Androida.
Te funkcje są dostępne w gałęzi studio-main
:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Tworzenie skompresowanych profili binarnych za pomocą narzędzia Profgen-cli
Polecenia dostępne w programie Profgen-cli to bin
, validate
i dumpProfile
. Aby zobaczyć dostępne polecenia, użyj 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
Aby wygenerować skompresowany profil binarny, użyj polecenia bin
. 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 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 baseline-prof.txt
HRF.
Narzędzie profgen-cli wymaga też ścieżki do wersji APK przeznaczonej do wydania oraz mapy zaciemnienia, która służy do zaciemnienia pliku APK podczas korzystania z R8 lub Proguard. Dzięki temu podczas tworzenia skompilowanego profilu profgen
może przekształcać symbole źródłowe w HRF w odpowiednie zaciemnione nazwy.
Formaty profili ART nie są kompatybilne wstecz ani wprzód, dlatego podaj format profilu, aby profgen
mogło przechowywać metadane profilu (profm
), których możesz używać do konwersji jednego formatu profilu ART na inny, gdy zajdzie taka potrzeba.
Formaty profilu i wersje platformy
Podczas wybierania formatu profilu dostępne są te opcje:
Format profilu | Wersja platformy | Poziom interfejsu API |
---|---|---|
v0_1_5_s | Android S+ | 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 zaciemnienia
Mapę zaciemnienia musisz przesłać tylko wtedy, gdy plik HRF używa symboli źródłowych. Jeśli HRF jest generowany z wersji wydania, 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 jeden z 2 sposobów.
Używanie install-multiple
z DexMetadata
Na urządzeniach z poziomem interfejsu API 28 lub nowszym klient Google Play pobiera plik APK oraz dane 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 pojedynczej sesji instalacji za pomocą:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Na urządzeniach z poziomem interfejsu API 29 lub nowszym biblioteka Jetpack ProfileInstaller zapewnia alternatywny mechanizm instalowania profilu spakowanego w plik assets
lub dexopt
po zainstalowaniu pliku APK na urządzeniu. ProfileInstaller
jest wywoływany przez ProfileInstallReceiver
lub bezpośrednio przez aplikację.
Biblioteka ProfileInstaller konwertuje profil na podstawie wersji SDK na urządzeniu docelowym i kopiuje go do katalogu cur
na urządzeniu (katalog pośredni dla profili ART na urządzeniu).
Gdy urządzenie jest nieaktywne, profil jest przechwytywany przez proces o nazwie bg-dexopt
na urządzeniu.
Przenoszenie profilu podstawowego
Z tej sekcji dowiesz się, jak zainstalować profil referencyjny za pomocą pliku APK.
Przesyłanie z urządzenia androidx.profileinstaller
Na urządzeniach z interfejsem API 24 lub nowszym możesz wysłać polecenie do 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>
Narzędzie ProfileInstaller nie występuje w większości plików APK z profilami podstawowymi (które są dostępne w około 77 tys. z 450 tys. aplikacji w Google Play), ale jest obecne w 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 możliwe od wersji Jetpacka.
Używanie install-multiple
z profgen lub DexMetaData
Na urządzeniach z interfejsem API 28 lub nowszym możesz załadować profil podstawowy bez konieczności umieszczania w aplikacji biblioteki ProfileInstaller.
Aby to zrobić, użyj narzędzia 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 umożliwić dzielenie plików APK, wykonaj poniższe czynności ekstrakcji profilu raz na plik APK. Podczas instalacji należy przekazać każdy plik APK i powiązany plik .dm
, z tym że nazwy plików APK i .dm
muszą być takie same:
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 artykule Ręczne pomiary ulepszeń w aplikacji.
Wyświetlanie zawartości profilu binarnego
Aby sprawdzić zawartość skompresowanej wersji binarnej profilu referencyjnego, użyj opcji profgen-cli dumpProfile
:
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 binarna reprezentacja przechowuje tylko przesunięcia DEX, a dlatego potrzebuje ich do odtworzenia nazw klas i metod.
Tryb ścisły jest domyślnie włączony i sprawdza zgodność profilu z plikami DEX w pliku APK. Jeśli próbujesz debugować profile wygenerowane przez inne narzędzie, możesz napotkać problemy ze zgodnością, które uniemożliwiają wygenerowanie pliku z danymi do analizy. W takich przypadkach możesz wyłączyć tryb ścisły za pomocą --strict false
. W większości przypadków jednak należy pozostawić włączony tryb ścisły.
Mapa zaciemnienia jest opcjonalna. Jeśli zostanie podana, pomoże zmapować zaciemnione symbole na wersje zrozumiałe dla człowieka, aby ułatwić korzystanie z usługi.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Sprawdzone metody dotyczące wydajności SQLite
- Profile podstawowe {:#baseline-profiles}
- Ciągłe częściowe blokady uśpienia