Creare e misurare manualmente i profili di riferimento

Ti consigliamo vivamente di automatizzare la generazione delle regole del profilo utilizzando la libreria Jetpack Macrobenchmark per ridurre lo sforzo manuale e aumentare la scalabilità generale. Tuttavia, puoi creare e misurare manualmente le regole del profilo nell'app.

Definisci manualmente le regole del profilo

Puoi definire manualmente le regole del profilo in un'app o in un modulo della libreria creando un file denominato baseline-prof.txt che si trova nella directory src/main. Questa è la stessa cartella che contiene il file AndroidManifest.xml.

Il file specifica una regola per riga. Ogni regola rappresenta un pattern per i metodi o le classi di corrispondenza nell'app o nella libreria che deve essere ottimizzata.

La sintassi di queste regole è un soprainsieme del formato di profilo ART (HRF) leggibile quando utilizzi adb shell profman --dump-classes-and-methods. La sintassi è simile alla sintassi per descrittori e firme, ma consente di utilizzare i caratteri jolly per semplificare il processo di scrittura delle regole.

L'esempio seguente mostra alcune regole del profilo di riferimento 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;

Sintassi delle regole

Queste regole assumono una delle due forme per il targeting di metodi o classi:

[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]

Una regola di classe utilizza il seguente pattern:

[CLASS_DESCRIPTOR]

Per una descrizione dettagliata, fai riferimento alla seguente tabella:

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 merito al tipo di avvio.

Un metodo con il flag H indica che si tratta di un metodo "ad accesso frequente", vale a dire che viene chiamato molte volte durante il ciclo di vita dell'app.

Un metodo con il flag S indica che si tratta di un metodo chiamato durante l'avvio.

Un metodo con il flag P indica che si tratta di un metodo richiamato dopo l'avvio.

Una classe presente in questo file indica che viene utilizzata durante l'avvio e deve essere preallocata nell'heap per evitare i costi di caricamento della classe. Il compilatore ART utilizza varie strategie di ottimizzazione, come la compilazione AOT di questi metodi e l'ottimizzazione del layout nel file AOT generato.
CLASS_DESCRIPTOR Descrittore della classe del metodo scelto come target. Ad esempio, androidx.compose.runtime.SlotTable ha un descrittore di Landroidx/compose/runtime/SlotTable;. L è anteposto qui secondo il formato Dalvik Executable (DEX).
METHOD_SIGNATURE Firma del metodo, inclusi nome, tipi di parametri e tipi restituiti. Ad esempio:

// LayoutNode.kt

fun isPlaced():Boolean {
// ...
}

su LayoutNode ha la firma isPlaced()Z.

Questi pattern possono avere caratteri jolly per avere una singola regola che comprende 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 con caratteri jolly potrebbe essere simile al seguente:

HSPLandroidx/compose/ui/layout/**->**(**)**

Tipi supportati nelle regole del profilo di riferimento

Le regole del profilo di riferimento supportano i seguenti tipi. Per maggiori dettagli su questi tipi, consulta il formato Dalvik Executable (DEX).

Carattere Tipo Descrizione
B byte Byte firmato
C caratteri Punto di codice carattere Unicode codificato in UTF-16
D doppio Valore in virgola mobile a precisione doppia
F numero in virgola mobile Valore in virgola mobile a precisione singola
I int Numero intero
J lunghi Numero intero lungo
S video breve Short firmato
V nullo Non valida
Z boolean Vero o falso
L (nome del corso) riferimento Un'istanza di un nome classe

Inoltre, le librerie possono definire regole pacchettizzate in artefatti AAR. Quando crei un APK per includere questi artefatti, le regole vengono unite, in modo simile all'unione del file manifest, e compilate in un profilo ART binario compatto specifico per l'APK.

ART utilizza questo profilo quando l'APK viene utilizzato sui dispositivi per compilare 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.

Raccogli manualmente i profili di riferimento

Puoi generare manualmente un profilo di riferimento senza configurare la libreria Macrobenchmark e creare automazioni UI dei percorsi critici degli utenti. Anche se consigliamo di utilizzare Macrobenchmarks, potrebbe non essere sempre possibile. Ad esempio, se utilizzi un sistema di compilazione non Gradle, non puoi utilizzare il plug-in Gradle del profilo Baseline. In questi casi, puoi raccogliere manualmente le regole del profilo di riferimento. Questa operazione è molto più semplice se usi un dispositivo o un emulatore con l'API 34 o versioni successive. Sebbene sia ancora possibile con livelli API inferiori, richiede l'accesso root e utilizzare un emulatore che esegue un'immagine AOSP. Puoi raccogliere le regole direttamente nel seguente modo:

  1. Installa una versione di release della tua app su un dispositivo di test. Per un profilo accurato, il tipo di build dell'app deve essere ottimizzato R8 e non può essere sottoposto a debug.
  2. Assicurati che i profili non siano già compilati.

    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
    

    Se il tuo APK ha una dipendenza dalla libreria Profile Installer Jetpack, la libreria esegue il bootstrap di un profilo al primo lancio dell'APK. Questo può interferire con il processo di generazione del profilo, quindi disabilitalo con il seguente comando:

    adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
    

  3. Esegui l'app ed esamina manualmente i percorsi dell'utente critici per i quali vuoi raccogliere un profilo.
  4. Chiedi ad ART di eseguire il dump dei profili. Se il tuo APK ha una dipendenza dalla libreria del programma di installazione del profilo Jetpack, utilizzala per eseguire il dump dei profili:

    adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
    adb shell am force-stop $PACKAGE_NAME
    
    Se non utilizzi il programma di installazione profili, scarica manualmente i profili in un emulatore utilizzando il seguente comando:

    adb root
    adb shell killall -s SIGUSR1 $PACKAGE_NAME
    adb shell am force-stop $PACKAGE_NAME
    

  5. Attendi almeno cinque secondi per il completamento della generazione del profilo.
  6. Converti i profili binari generati in testo:

    API 34 e versioni successive

    adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
    

    API 33 e versioni precedenti

    Determinare se è stato creato un profilo di riferimento o uno corrente. Un profilo di riferimento si trova nella seguente posizione:

    /data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
    

    Un profilo corrente si trova nella seguente posizione:

    /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
    

  7. Usa adb per recuperare il profilo di cui è stato eseguito il dump dal dispositivo:

    adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
    

Questa operazione estrae le regole del profilo generate e le installa nel modulo dell'app. La volta successiva che creerai l'app, sarà incluso il profilo di riferimento. Per verificarlo, segui i passaggi descritti in Problemi di installazione.

Misura manualmente i miglioramenti dell'app

Ti consigliamo vivamente di misurare i miglioramenti delle app tramite il benchmarking. Tuttavia, se vuoi misurare i miglioramenti manualmente, puoi iniziare misurando l'avvio dell'app non ottimizzato per 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"

Quindi, installa il profilo di riferimento tramite sideload.

# 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 al momento dell'installazione, esegui questo comando:

# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME

L'output deve indicare che il pacchetto è stato compilato:

[com.example.app]
  path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
  arm64: [status=speed-profile] [reason=install-dm]

Ora puoi misurare le prestazioni 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 e profilo di riferimento

Questa sezione descrive che cosa fa lo strumento profgen quando crea una versione binaria compatta di un profilo di riferimento.

Profgen-cli semplifica la compilazione dei profili, l'introspezione e la transcodifica dei profili ART, in modo che possano essere installati su dispositivi basati su Android indipendentemente dalla versione target dell'SDK.

Profgen-cli è un'interfaccia a riga di comando che compila l'HRF di un profilo di riferimento nel suo formato compilato. L'interfaccia a riga di comando viene anche fornita 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 l'interfaccia a riga di comando Profgen 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 è riportata una chiamata di esempio:

profgen bin ./baseline-prof.txt \
  --apk ./release.apk \
  --map ./obfuscation-map.txt \
  --profile-format v0_1_0_p \
  --output ./baseline.prof \

Per vedere le opzioni disponibili, usa 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 all'HRF baseline-prof.txt.

Profgen-cli richiede anche il percorso per la build della release dell'APK e una mappa di offuscamento che viene utilizzata per offuscare l'APK quando si utilizza R8 o Proguard. In questo modo, profgen può tradurre i simboli di origine nella sezione HRF nei nomi offuscati corrispondenti durante la creazione del profilo compilato.

Poiché i formati dei profili ART non sono compatibili in avanti o indietro, fornisci un formato profilo in modo che profgen pacchettizza i metadati del profilo (profm) da utilizzare per transcodificare un formato di profilo ART in un altro quando necessario.

Formati del profilo e versioni della piattaforma

Quando scegli un formato di profilo, sono disponibili le seguenti opzioni:

Formato del profilo Versione piattaforma Livello API
v0_1_5_s Android S e versioni successive 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 l'HRF viene generato da una build di release già offuscata e non è necessario alcun mapping, puoi ignorare questa opzione e copiare gli output nella cartella assets o dexopt.

Installazione tradizionale dei profili di riferimento

I profili di riferimento vengono tradizionalmente inviati a un dispositivo in uno dei due modi seguenti.

Utilizza install-multiple con DexMetadata

Sui dispositivi che eseguono l'API 28 e versioni successive, il client Play scarica il payload APK e DeexMetadata (DM) per una versione APK in fase di installazione. Il messaggio diretto contiene le informazioni del profilo trasmesse a Gestione pacchetti sul dispositivo.

L'APK e il file DM vengono installati come parte di una singola sessione di installazione tramite qualcosa del tipo:

adb install-multiple base.apk base.dm

Programma di installazione del profilo Jetpack

Sui dispositivi con livello API 29 e versioni successive, la libreria Jetpack ProfileInstaller fornisce un meccanismo alternativo per installare un profilo pacchettizzato in assetso dexopt dopo l'installazione dell'APK sul dispositivo. ProfileInstaller è richiamato da ProfileInstallReceiver o direttamente dall'app.

La libreria ProfileInstaller transcodifica il profilo in base alla versione dell'SDK del dispositivo di destinazione e copia il profilo nella directory cur sul dispositivo (una directory temporanea specifica del pacchetto per i profili ART sul dispositivo).

Quando il dispositivo è inattivo, il profilo viene rilevato da un processo chiamato bg-dexopt sul dispositivo.

Eseguire il sideload di un profilo di riferimento

Questa sezione descrive come installare un profilo di riferimento per un APK.

Trasmetti con androidx.profileinstaller

Sui dispositivi che eseguono l'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 i profili Baseline, che comprende circa 77.000 delle 450.000 app in Play, sebbene sia presente in effetti in ogni APK che utilizza Compose. Questo perché le librerie possono fornire profili senza dichiarare una dipendenza su ProfileInstaller. L'aggiunta di una dipendenza in ogni libreria con un profilo si applica a partire da Jetpack.

Utilizza install-multiple con profgen o DexMetaData

Sui dispositivi che eseguono l'API 28 e versioni successive, puoi installare un profilo di riferimento senza dover avere 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 di estrazione precedenti del profilo una volta per ogni APK. Al momento dell'installazione, passa ogni APK e file .dm associato, assicurandoti che i nomi di APK e .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 delle app.

Esegui il dump dei contenuti di un profilo binario

Per analizzare i contenuti di una versione binaria compatta di un profilo di riferimento, utilizza l'opzione dumpProfile dell'interfaccia a riga di comando Profgen:

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 archivia solo gli offset DEX e, di conseguenza, ha bisogno di questi ultimi per ricostruire i nomi di classi e metodi.

La modalità rigorosa è attivata per impostazione predefinita e consente di eseguire un controllo di compatibilità del profilo con i file DEX nell'APK. Se stai tentando di eseguire il debug di profili generati da un altro strumento, potresti ricevere errori di compatibilità che ti impediscono di eseguire il dump per effettuare accertamenti. In questi casi, puoi disattivare la modalità con restrizioni con --strict false. Tuttavia, nella maggior parte dei casi dovresti attivare la modalità con restrizioni.

Una mappa di offuscamento è facoltativa; se fornita, aiuta a rimappare i simboli offuscati alle relative versioni leggibili da una persona per facilitarne l'uso.