Ti consigliamo vivamente di automatizzare la generazione di regole del profilo utilizzando la libreria Jetpack Macrobenchmark per ridurre l'impegno manuale e aumentare la scalabilità generale. Tuttavia, è possibile creare e misurare manualmente le regole del profilo nella tua app.
Definisci manualmente le regole del profilo
Puoi definire manualmente le regole del profilo in un modulo di un'app o di una libreria creando
un file denominato baseline-prof.txt
che si trova nella directory src/main
. Si tratta
della stessa cartella che contiene il file AndroidManifest.xml
.
Il file specifica una regola per riga. Ogni regola rappresenta un pattern per corrispondere a metodi o classi nell'app o nella libreria che devono essere ottimizzati.
La sintassi di queste regole è un superset del formato del profilo ART leggibile
dall'uomo (HRF) quando si utilizza adb shell profman --dump-classes-and-methods
. La sintassi è simile alla sintassi per i descrittori e le firme, ma consente di utilizzare caratteri jolly per semplificare il processo di scrittura delle regole.
L'esempio seguente mostra alcune regole del profilo di base incluse nella libreria 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;
Puoi provare a modificare le regole del profilo in questo progetto di esempio di Compiler Explorer. Tieni presente che Compiler Explorer supporta solo il formato del profilo ART leggibile (HRF), pertanto i caratteri jolly non sono supportati.
Sintassi delle regole
Queste regole assumono una delle due forme per scegliere come target metodi o classi:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Una regola di classe utilizza il seguente pattern:
[CLASS_DESCRIPTOR]
Per una descrizione dettagliata, consulta la tabella riportata di seguito:
Sintassi | Descrizione |
---|---|
FLAGS |
Rappresenta uno o più caratteri H , S e P per indicare se questo metodo deve essere contrassegnato come Hot , Startup o Post Startup in relazione al tipo di avvio. Un metodo con il flag H indica che è un metodo "hot", ovvero viene chiamato molte volte durante il ciclo di vita dell'app. Un metodo con il flag S indica che è un metodo chiamato durante l'avvio. Un metodo con il flag P indica che si tratta di un metodo chiamato dopo l'avvio. Una classe presente in questo file indica che viene utilizzata durante l'avvio e deve essere preallocata nell'heap per evitare il costo del caricamento della classe. Il compilatore ART utilizza varie strategie di ottimizzazione, come la compilazione AOT di questi metodi e l'esecuzione di ottimizzazioni del layout nel file AOT generato. |
CLASS_DESCRIPTOR |
Descrittore per la classe del metodo di destinazione. Ad esempio, androidx.compose.runtime.SlotTable ha un descrittore di Landroidx/compose/runtime/SlotTable; . La lettera L viene anteposta qui in base al formato Dalvik Executable (DEX). |
METHOD_SIGNATURE |
Firma del metodo, inclusi nome, tipi di parametri e tipi restituiti del metodo. Ad esempio:// LayoutNode.kt fun isPlaced():Boolean { // ... } su LayoutNode ha la firma isPlaced()Z . |
Questi pattern possono contenere caratteri jolly per consentire a una singola regola di includere più metodi o classi. Per assistenza guidata durante la scrittura con la sintassi delle regole in Android Studio, consulta il plug-in Android Baseline Profiles.
Un esempio di regola jolly potrebbe avere il seguente aspetto:
HSPLandroidx/compose/ui/layout/**->**(**)**
Tipi supportati nelle regole del profilo di base
Le regole del profilo di base supportano i seguenti tipi. Per informazioni dettagliate su questi tipi, consulta il formato Dalvik Executable (DEX).
Carattere | Tipo | Descrizione |
---|---|---|
B |
byte | Byte con segno |
C |
char | Punto di codice carattere Unicode codificato in UTF-16 |
D |
doppio | Valore in virgola mobile a precisione doppia |
F |
float | Valore in virgola mobile a precisione singola |
I |
int | Numero intero |
J |
lunghi | Numero intero lungo |
S |
video breve | Short firmato |
V |
void | Annulla |
Z |
booleano | Vero o falso |
L (nome del corso) |
riferimento | Un'istanza di un nome di classe |
Inoltre, le librerie possono definire regole incluse negli artefatti AAR. Quando crei un APK per includere questi artefatti, le regole vengono unite, in modo simile a come viene eseguita l'unione dei manifest, e compilate in un profilo binario ART compatto specifico per l'APK.
ART sfrutta questo profilo quando l'APK viene utilizzato sui dispositivi per la compilazione AOT di un sottoinsieme specifico dell'app al momento dell'installazione su Android 9 (livello API 28) o Android 7 (livello API 24) quando si utilizza ProfileInstaller
.
Raccogliere manualmente i profili di base
Puoi generare manualmente un profilo di base senza configurare la libreria Macrobenchmark e creare automazioni UI dei percorsi utente critici. Anche se consigliamo di utilizzare Macrobenchmark, potrebbe non essere sempre possibile. Ad esempio, se utilizzi un sistema di build non Gradle, non puoi utilizzare il plug-in Gradle per i profili di base. In questi casi, puoi raccogliere manualmente le regole del profilo di base. Questa operazione è molto più semplice se utilizzi un dispositivo o un emulatore con API 34 e versioni successive. Sebbene sia ancora possibile con livelli API inferiori, richiede l'accesso root e devi utilizzare un emulatore che esegue un'immagine AOSP. Puoi raccogliere le regole direttamente nel seguente modo:
- Installa una versione di release della tua app su un dispositivo di test. Il tipo di build dell'app non deve essere ottimizzato per R8 e non deve essere eseguibile in modalità di debug per acquisire un profilo che possa essere utilizzato dal sistema di build.
- Disattiva l'installazione del profilo e chiudi l'app.
Se il tuo APK ha una dipendenza dalla libreria Profile Installer di Jetpack, la libreria esegue il bootstrap di un profilo al primo avvio dell'APK. Ciò può interferire con il processo di generazione del profilo, quindi disattivalo con il seguente comando:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
Reimposta la compilazione delle app e cancella tutti i profili.
API 34 e versioni successive
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
API 33 e versioni precedenti
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Esegui l'app e naviga manualmente nei percorsi utente critici per i quali vuoi raccogliere un profilo.
Attendi almeno cinque secondi affinché i profili si stabilizzino.
Esegui l'azione di salvataggio e attendi il completamento del salvataggio. Se il tuo APK ha una dipendenza dalla libreria Jetpack Profile Installer, utilizzala per scaricare i profili:
Se non utilizzi Profile Installer, scarica manualmente i profili su un emulatore utilizzando il seguente comando: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
Converti in testo i profili binari generati:
API 34 e versioni successive
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
API 33 e versioni precedenti
Determina se è stato creato un profilo di riferimento o un profilo attuale. Un profilo di riferimento si trova nel seguente percorso:
/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Un profilo attuale si trova nel seguente percorso:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Determina la posizione dell'APK:
adb root adb shell pm path $PACKAGE_NAME
Esegui la conversione:
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
Utilizza
adb
per recuperare il profilo scaricato dal dispositivo:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Vengono recuperate le regole del profilo generate e installate nel modulo dell'app. La volta successiva che crei l'app, il profilo di base viene incluso. Verifica questo aspetto seguendo i passaggi descritti in Problemi di installazione.
Misurare manualmente i miglioramenti dell'app
Ti consigliamo vivamente di misurare i miglioramenti dell'app tramite il benchmarking. Tuttavia, se vuoi misurare i miglioramenti manualmente, puoi iniziare misurando l'avvio dell'app non ottimizzata come riferimento.
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"
Poi, carica lateralmente il profilo di base.
# 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
Per verificare che il pacchetto sia stato ottimizzato durante l'installazione, esegui questo comando:
# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME
L'output deve indicare che il pacchetto è compilato:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Ora puoi misurare il rendimento dell'avvio dell'app come prima, ma senza reimpostare lo stato compilato. Assicurati di non reimpostare lo stato compilato per il pacchetto.
# 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"
Profili di base e profgen
Questa sezione descrive cosa fa lo strumento profgen durante la creazione di una versione binaria compatta di un profilo di base.
Profgen-cli aiuta con la compilazione, l'introspezione e la transpilazione dei profili ART, in modo che possano essere installati su dispositivi Android indipendentemente dalla versione dell'SDK di destinazione.
Profgen-cli è una CLI che compila l'HRF di un profilo di base nel suo
formato compilato. L'interfaccia a riga di comando viene fornita anche nel repository cmdline-tools
come parte dell'SDK Android.
Queste funzionalità sono disponibili nel ramo studio-main
:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Crea profili binari compatti con Profgen-cli
I comandi disponibili con Profgen-cli sono bin
, validate
e dumpProfile
. Per visualizzare i comandi disponibili, utilizza 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
Utilizza il comando bin
per generare il profilo binario compatto. Di seguito è riportato un esempio di chiamata:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Per visualizzare le opzioni disponibili, utilizza 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
Il primo argomento rappresenta il percorso del file baseline-prof.txt
HRF.
Profgen-cli ha bisogno anche del percorso della build di release dell'APK e di una
mappa di offuscamento utilizzata per offuscare l'APK quando
si utilizza R8 o Proguard. In questo modo, profgen
può tradurre i simboli di origine nel
file HRF nei nomi offuscati corrispondenti durante la creazione del profilo compilato.
Poiché i formati dei profili ART non sono compatibili con le versioni precedenti o successive, fornisci un formato del profilo in modo che profgen
pacchetti i metadati del profilo (profm
) che puoi utilizzare per transcodificare un formato del profilo ART in un altro, se necessario.
Formati dei profili e versioni delle piattaforme
Quando scegli un formato del profilo, sono disponibili le seguenti opzioni:
Formato del profilo | Versione piattaforma | Livello API |
---|---|---|
v0_1_5_s | Android S+ | 31+ |
v0_1_0_p | Android P, Q e 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 |
Copia i file di output baseline.prof
e baseline.profm
nella cartella
assets
o dexopt
dell'APK.
Mappe di offuscamento
Devi fornire la mappa di offuscamento solo se l'HRF utilizza simboli di origine. Se
il file HRF viene generato da una build di rilascio già offuscata e
non è necessaria alcuna mappatura, puoi ignorare questa opzione e copiare gli output
nella cartella assets
o dexopt
.
Installazione tradizionale dei profili di base
I profili di base vengono tradizionalmente inviati a un dispositivo in uno dei due modi seguenti.
Utilizzare install-multiple
con DexMetadata
Sui dispositivi con API 28 e versioni successive, il client Play scarica l'APK e il payload DexMetadata (DM) per una versione dell'APK in fase di installazione. Il DM contiene le informazioni del profilo che vengono trasmesse a Package Manager sul dispositivo.
L'APK e il DM vengono installati nell'ambito di una singola sessione di installazione utilizzando un comando simile a questo:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
Sui dispositivi con livello API 29 e versioni successive, la libreria Jetpack
ProfileInstaller fornisce un meccanismo
alternativo per installare un profilo incluso in assets
o dexopt
dopo l'installazione dell'APK
sul dispositivo. ProfileInstaller
viene richiamato da
ProfileInstallReceiver
o direttamente dall'app.
La libreria ProfileInstaller transcodifica il profilo in base alla versione SDK del dispositivo di destinazione e lo copia nella directory cur
sul dispositivo (una directory di gestione temporanea specifica per il pacchetto per i profili ART sul dispositivo).
Una volta che il dispositivo è inattivo, il profilo viene rilevato da un processo chiamato
bg-dexopt
sul dispositivo.
Caricare in sideload un profilo di base
Questa sezione descrive come installare un profilo di base dato un APK.
Trasmetti con androidx.profileinstaller
Sui dispositivi con API 24 e versioni successive, puoi trasmettere un comando per installare il profilo:
# 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 non è presente nella maggior parte degli APK con profili di base, ovvero in circa 77.000 delle 450.000 app su Play, anche se è presente in praticamente tutti gli APK che utilizzano Compose. Questo perché le librerie possono fornire profili senza dichiarare una dipendenza da ProfileInstaller. L'aggiunta di una dipendenza in ogni libreria con un profilo viene applicata a partire da Jetpack.
Utilizzare install-multiple
con profgen o DexMetaData
Sui dispositivi con API 28 e versioni successive, puoi caricare lateralmente un profilo di base senza dover includere la libreria ProfileInstaller nell'app.
Per farlo, utilizza 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
Per supportare le suddivisioni degli APK, esegui i passaggi precedenti di estrazione del profilo una volta per ogni APK. Al momento
dell'installazione, passa ogni APK e il file .dm
associato, assicurandoti che i nomi dell'APK e
del file .dm
corrispondano:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Verifica
Per verificare che il profilo sia installato correttamente, puoi seguire i passaggi descritti in Misurare manualmente i miglioramenti dell'app.
Dump the contents of a binary profile
Per esaminare i contenuti di una versione binaria compatta di un
profilo di base, utilizza l'opzione 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
ha bisogno dell'APK perché la rappresentazione binaria compatta memorizza solo gli offset DEX e, pertanto, ne ha bisogno per ricostruire i nomi di classi e metodi.
La modalità Strict è attivata per impostazione predefinita ed esegue un controllo di compatibilità del profilo con i file DEX nell'APK. Se stai tentando di eseguire il debug dei profili
generati da un altro strumento, potresti riscontrare errori di compatibilità che
impediscono di eseguire il dump per l'analisi. In questi casi, puoi
disattivare la modalità più restrittiva con --strict false
. Tuttavia, nella maggior parte dei casi, ti consigliamo di mantenere attiva la modalità più restrittiva.
Una mappa di offuscamento è facoltativa; se fornita, aiuta a rimappare i simboli offuscati alle loro versioni leggibili per facilitarne l'utilizzo.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Best practice per le prestazioni di SQLite
- Profili di base {:#baseline-profiles}
- Wakelock parziali bloccati