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ć reguły profilu i mierzyć je w aplikacji.
Ręczne definiowanie reguł profili
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, w którym znajduje się plik AndroidManifest.xml
.
W pliku każda reguła jest podana w osobnym 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 czytelnego dla człowieka (HRF) w przypadku używania 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 tworzenia reguł.
Poniższy 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 czytelny dla człowieka (HRF), więc symbole wieloznaczne nie są obsługiwane.
Składnia reguły
Te reguły przyjmują jedną z 2 form, aby kierować reklamy na metody lub klasy:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Reguła klasy ma następujący wzór:
[CLASS_DESCRIPTOR]
Szczegółowy opis znajdziesz w tabeli poniżej:
Składnia | Opis |
---|---|
FLAGS |
Reprezentuje jeden lub więcej znaków H , S i P , aby wskazać, czy ta metoda musi być oznaczona jako Hot , Startup lub Post Startup w odniesieniu do 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 wywoływana podczas uruchamiania. Metoda z flagą P oznacza, ż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 stercie, aby uniknąć kosztów ładowania klasy. Kompilator ART wykorzystuje różne strategie optymalizacji, takie jak kompilacja AOT tych metod i optymalizacja układu w wygenerowanym pliku AOT. |
CLASS_DESCRIPTOR |
Deskryptor klasy kierowanej metody. Na przykład androidx.compose.runtime.SlotTable ma deskryptor Landroidx/compose/runtime/SlotTable; . Przedrostek L jest dodawany zgodnie z formatem pliku wykonywalnego Dalvik (DEX). |
METHOD_SIGNATURE |
Sygnatura metody, w tym nazwa, typy parametrów i typy zwracanych wartości. Na przykład:// LayoutNode.kt fun isPlaced():Boolean { // ... } na LayoutNode ma podpis isPlaced()Z . |
Wzorce te mogą zawierać symbole wieloznaczne, dzięki czemu jedna reguła może obejmować wiele metod lub klas. Aby uzyskać pomoc podczas pisania z użyciem składni reguł w Android Studio, zapoznaj się z wtyczką Android Baseline Profiles.
Przykładowa reguła z symbolem wieloznacznym 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: Więcej informacji o tych typach znajdziesz w artykule Format pliku wykonywalnego Dalvik (DEX).
Znak | Typ | Opis |
---|---|---|
B |
bajt | Bajt ze znakiem |
C |
char | Punkt kodowy znaku Unicode zakodowany w UTF-16 |
D |
podwójny | 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 | Podpisany film Short |
V |
pusty, | Anuluj |
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 artefakty AAR. Gdy tworzysz plik APK, aby uwzględnić te artefakty, reguły są łączone ze sobą – podobnie jak w przypadku łączenia plików manifestu – 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 kompilacji AOT określonego podzbioru aplikacji w momencie instalacji na Androidzie 9 (poziom interfejsu API 28) lub Androidzie 7 (poziom interfejsu API 24) w przypadku korzystania z ProfileInstaller
.
Ręczne zbieranie profili podstawowych
Możesz ręcznie wygenerować profil podstawowy bez konfigurowania biblioteki Macrobenchmark i utworzyć automatyzację interfejsu użytkownika w przypadku najważniejszych ścieżek użytkownika. Zalecamy używanie testów Macrobenchmark, ale 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 zebrać reguły profilu podstawowego. Jest to znacznie łatwiejsze, jeśli używasz urządzenia lub emulatora z 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ę aplikacji na urządzeniu testowym. Typ kompilacji aplikacji nie może być zoptymalizowany pod kątem R8 ani nie może być debugowany, 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 Twój plik APK jest zależny od biblioteki Jetpack Profile Installer, biblioteka ta uruchamia profil przy pierwszym uruchomieniu pliku APK. Może to zakłócać 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 na poziomie 33 lub niższym
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 Instalator profili Jetpack, użyj jej do zrzucenia profili:
Jeśli nie używasz instalatora profili, ręcznie wyeksportuj profile na 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
Przekształć 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 na poziomie 33 lub niższym
Sprawdź, czy utworzono profil referencyjny lub bieżący. Profil referencyjny 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
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
Użyj polecenia
adb
, aby pobrać zrzucony profil z urządzenia: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ępnym kompilowaniu aplikacji zostanie uwzględniony profil podstawowy. Aby to sprawdzić, wykonaj czynności opisane w sekcji Problemy z instalacją.
Ręczne pomiary ulepszeń aplikacji
Zdecydowanie zalecamy mierzenie ulepszeń aplikacji za pomocą testów porównawczych. Jeśli jednak chcesz mierzyć postępy ręcznie, możesz zacząć od pomiaru nieoptymalizowanego uruchamiania aplikacji w celu uzyskania wartości odniesienia.
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 wgraj 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 resetujesz 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 opisujemy, co robi narzędzie profgen podczas tworzenia kompaktowej wersji binarnej profilu podstawowego.
Profgen-cli pomaga w kompilacji, 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 plik HRF profilu podstawowego do skompilowanego formatu. Interfejs wiersza poleceń jest też dostępny w repozytorium cmdline-tools
w ramach 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 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ć kompaktowy profil binarny, użyj polecenia bin
. Oto przykładowe wywołanie:
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 to ścieżka do pliku baseline-prof.txt
HRF.
Profgen-cli potrzebuje też ścieżki do wersji APK i mapy zaciemniania, która służy do zaciemniania pliku APK podczas korzystania z R8 lub Proguard. W ten sposób profgen
może tłumaczyć symbole źródłowe w pliku HRF na odpowiadające im zaciemnione nazwy podczas tworzenia skompilowanego profilu.
Formaty profili ART nie są kompatybilne wstecz ani w przód, dlatego podaj format profilu, aby pakiet profgen
zawierał metadane profilu (profm
), których możesz użyć do transkodowania jednego formatu profilu ART na inny w razie potrzeby.
Formaty profili i wersje platform
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 zaciemniania
Mapę zaciemniania musisz przesłać tylko wtedy, gdy plik HRF używa symboli źródłowych. Jeśli plik HRF jest generowany na podstawie wersji, która jest już zaciemniona i nie wymaga mapowania, możesz zignorować tę opcję i skopiować dane wyjściowe do folderu assets
lub dexopt
.
Tradycyjna instalacja profili podstawowych
Profile podstawowe są zwykle dostarczane na urządzenie na jeden z 2 sposobów.
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 APK. DM zawiera informacje o profilu, które są przekazywane do Menedżera pakietów na urządzeniu.
Pliki APK i DM są instalowane w ramach jednej sesji instalacji, np. za pomocą tego kodu:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Na urządzeniach z interfejsem API na poziomie 29 lub nowszym biblioteka Jetpack
ProfileInstaller zapewnia alternatywny mechanizm instalowania profilu spakowanego w assets
lub dexopt
po zainstalowaniu pliku APK na urządzeniu. ProfileInstaller
jest wywoływana przez ProfileInstallReceiver
lub bezpośrednio przez aplikację.
Biblioteka ProfileInstaller transkoduje profil na podstawie wersji pakietu SDK urządzenia docelowego i kopiuje go do katalogu cur
na urządzeniu (katalogu przejściowego specyficznego dla pakietu na potrzeby profili ART na urządzeniu).
Gdy urządzenie jest nieaktywne, 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łaj za pomocą: androidx.profileinstaller
Na urządzeniach z API w wersji 24 lub nowszej możesz rozgłosić 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>
Instalator profili nie występuje w większości plików APK z profilami podstawowymi (czyli w około 77 tys. z 450 tys. aplikacji w Google Play), ale jest obecny w praktycznie każdym pliku APK korzystającym z Compose. Wynika to z faktu, że 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 Jetpacka.
Używanie install-multiple
z profgen lub DexMetaData
Na urządzeniach z API 28 lub nowszym możesz wgrać profil podstawowy bez konieczności umieszczania w aplikacji biblioteki ProfileInstaller.
W tym celu 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ć podzielone pliki APK, wykonaj powyższe czynności związane z wyodrębnianiem profilu raz dla każdego pliku APK. Podczas instalacji przekaż każdy plik APK i powiązany z nim plik .dm
, upewniając się, że nazwy pliku APK i pliku .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 artykule Ręczne pomiary ulepszeń aplikacji.
Zrzucanie zawartości profilu binarnego
Aby sprawdzić zawartość skompaktowanej wersji binarnej profilu podstawowego, 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 reprezentacja binarna przechowuje tylko przesunięcia DEX, a więc potrzebuje ich do odtworzenia nazw klas i metod.
Tryb ścisły jest domyślnie włączony i sprawdza zgodność profilu z plikami DEX w pakiecie APK. Jeśli próbujesz debugować profile wygenerowane przez inne narzędzie, mogą wystąpić błędy zgodności, które uniemożliwią zrzucenie danych do analizy. W takich przypadkach możesz wyłączyć tryb ścisły za pomocą ikony --strict false
. W większości przypadków tryb ścisły powinien być jednak włączony.
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 z nich.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Sprawdzone metody zwiększania wydajności SQLite
- Profile podstawowe {:#baseline-profiles}
- Ciągłe częściowe blokady uśpienia