Questa pagina illustra come configurare ART e le sue opzioni di compilazione. Gli argomenti qui trattati includono la configurazione della precompilazione dell'immagine di sistema, le opzioni di compilazione di dex2oat e come scambiare spazio di partizione di sistema, spazio di partizione dati e prestazioni.
Vedere ART e Dalvik , il formato eseguibile di Dalvik e le pagine rimanenti su source.android.com per lavorare con ART. Consulta Verifica del comportamento delle app su Android Runtime (ART) per assicurarti che le tue app funzionino correttamente.
Come funziona ART
ART usa la compilazione anticipata (AOT) e, a partire da Android 7.0 (Nougat o N), usa una combinazione ibrida di AOT, compilazione just-in-time (JIT) e compilazione guidata dal profilo. La combinazione di tutte queste modalità di compilazione è configurabile e verrà discussa in questa sezione. Ad esempio, i dispositivi Pixel sono configurati con il seguente flusso di compilazione:
- Un'applicazione viene inizialmente installata senza alcuna compilazione AOT. Le prime volte che l'applicazione viene eseguita, viene interpretata e i metodi eseguiti di frequente vengono compilati JIT.
- Quando il dispositivo è inattivo e in carica, un demone di compilazione viene eseguito per compilare AOT il codice utilizzato di frequente in base a un profilo generato durante le prime esecuzioni.
- Il successivo riavvio di un'applicazione utilizza il codice guidato dal profilo ed evita di eseguire la compilazione JIT in fase di esecuzione per i metodi già compilati. I metodi che vengono compilati con JIT durante le nuove esecuzioni vengono aggiunti al profilo, che verrà quindi prelevato dal demone di compilazione.
ART comprende un compilatore (lo strumento dex2oat
) e un runtime ( libart.so
) che viene caricato per avviare Zygote. Lo strumento dex2oat
prende un file APK e genera uno o più file di elementi di compilazione caricati dal runtime. Il numero di file, le loro estensioni e i nomi sono soggetti a modifiche tra le versioni, ma a partire dalla versione Android 8, i file generati sono:
-
.vdex
: contiene il codice DEX non compresso dell'APK, con alcuni metadati aggiuntivi per velocizzare la verifica. -
.odex
: contiene il codice compilato AOT per i metodi nell'APK. -
.art (optional)
: contiene le rappresentazioni interne ART di alcune stringhe e classi elencate nell'APK, utilizzate per velocizzare l'avvio dell'applicazione.
Opzioni di compilazione
Le opzioni di compilazione per ART sono di due categorie:
- Configurazione della ROM di sistema: quale codice viene compilato in AOT durante la creazione di un'immagine di sistema.
- Configurazione runtime: come ART compila ed esegue le applicazioni su un dispositivo.
Un'opzione ART fondamentale per configurare queste due categorie sono i filtri del compilatore . I filtri del compilatore guidano il modo in cui ART compila il codice DEX ed è un'opzione passata allo strumento dex2oat
. A partire da Android 8, ci sono quattro filtri ufficialmente supportati:
-
verify
: eseguire solo la verifica del codice DEX. -
quicken
: (rimosso da Android 12) esegui la verifica del codice DEX e ottimizza alcune istruzioni DEX per ottenere prestazioni migliori dell'interprete. -
speed
: esegui la verifica del codice DEX e compila AOT tutti i metodi. -
speed-profile
: esegui la verifica del codice DEX e i metodi di compilazione AOT elencati in un file di profilo.
Configurazione della ROM di sistema
Sono disponibili numerose opzioni di build ART per la configurazione di una ROM di sistema. La modalità di configurazione di queste opzioni dipende dallo spazio di archiviazione disponibile per l'immagine di sistema e dal numero di applicazioni preinstallate. I JAR/APK compilati in una ROM di sistema possono essere suddivisi in quattro categorie:
- Codice del percorso di classe di avvio: compilato con il filtro del compilatore
speed-profile
per impostazione predefinita. - Codice del server di sistema (consultare
PRODUCT_SYSTEM_SERVER_JARS
,PRODUCT_APEX_SYSTEM_SERVER_JARS
,PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
,PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
più avanti in questo documento):- (da Android 14 (AOSP sperimentale)) compilato con il filtro del compilatore
speed-profile
per impostazione predefinita o compilato con il filtro del compilatore dispeed
se non viene fornito un profilo. - (fino ad Android 13) compilato con il filtro del compilatore di
speed
per impostazione predefinita.
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
(vedi più avanti in questo documento). - (da Android 14 (AOSP sperimentale)) compilato con il filtro del compilatore
- Applicazioni core specifiche del prodotto (vedi
PRODUCT_DEXPREOPT_SPEED_APPS
più avanti in questo documento): compilate con il filtro del compilatore dispeed
per impostazione predefinita. - Tutte le altre applicazioni: compilate con il filtro del compilatore
speed-profile
per impostazione predefinita o compilate con il filtro del compilatore diverify
se non viene fornito un profilo.Configurabile tramite
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
(vedi più avanti in questo documento).
Opzioni di makefile
-
WITH_DEXPREOPT
-
DONT_DEXPREOPT_PREBUILTS
(da Android 5) -
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
(da Android 9) -
WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
(nuovo in Android 8 MR1) -
LOCAL_DEX_PREOPT
-
PRODUCT_DEX_PREOPT_BOOT_FLAGS
-
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
-
PRODUCT_DEX_PREOPT_MODULE_CONFIGS
-
PRODUCT_DEXPREOPT_SPEED_APPS (New in Android 8)
-
PRODUCT_SYSTEM_SERVER_APPS (New in Android 8)
-
PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(Post Android 8)
-
WITH_DEXPREOPT_PIC (Removed in Android 8)
-
WITH_DEXPREOPT_BOOT_IMG_ONLY
(rimosso in Android 8 MR1) -
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
- (da Android 14 (AOSP sperimentale)) Se non specificato, viene utilizzato il filtro del compilatore
speed-profile
oppure viene utilizzato il filtro del compilatore dispeed
se non viene fornito un profilo. - (fino ad Android 13) Se non specificato, viene utilizzato il filtro del compilatore di
speed
. - Se impostato su
speed
, viene utilizzato il filtro del compilatore dispeed
. - Se impostato su
speed-profile
, viene usato il filtro del compilatorespeed-profile
oppure viene usato il filtro del compilatore diverify
se non viene fornito un profilo. - Se impostato su
verify
verify
-
PRODUCT_SYSTEM_SERVER_JARS
,PRODUCT_APEX_SYSTEM_SERVER_JARS
,PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
,PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
- (obbligatorio)
PRODUCT_SYSTEM_SERVER_JARS
: elenco di file jar del percorso di classe del server di sistema sulla piattaforma (ad esempio, come parte diSYSTEMSERVERCLASSPATH
). È necessario aggiungere i file jar del percorso di classe del server di sistema a questo elenco. La mancata aggiunta di jar del percorso di classe del server di sistema all'elenco comporta il mancato caricamento di tali jar. - (obbligatorio)
PRODUCT_APEX_SYSTEM_SERVER_JARS
: elenco di file jar del percorso di classe del server di sistema forniti tramite apex (ovvero, come parte diSYSTEMSERVERCLASSPATH
). Il formato è<apex name>:<jar name>
. È necessaria l'aggiunta di file jar del percorso di classe del server di sistema Apex a questo elenco. La mancata aggiunta dei jar del percorso di classe del server di sistema Apex a questo elenco comporta il mancato caricamento di tali jar. - (facoltativo, da Android 13)
PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
: elenco di jar che il server di sistema carica dinamicamente utilizzando classloader separati (tramiteSystemServiceManager.startServiceFromJar
). L'aggiunta di jar di server di sistema standalone a questo elenco non è richiesta ma è fortemente consigliata perché rende i jar compilati e quindi ha buone prestazioni di runtime. - (obbligatorio, da Android 13)
PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
: elenco di jar forniti tramite apex che il server di sistema carica dinamicamente utilizzando classloader separati (ad esempio, tramiteSystemServiceManager.startServiceFromJar
o dichiarati come<apex-system-service>
). Il formato è<apex name>:<jar name>
. È necessaria l'aggiunta di jar del server di sistema Apex autonomo a questo elenco. La mancata aggiunta di jar del server di sistema Apex autonomo a questo elenco provoca un errore di avvio. - Elenco classi precaricato
Se dex2oat
viene invocato sul codice DEX installato nell'immagine di sistema. Abilitato per impostazione predefinita.
L'abilitazione DONT_DEXPREOPT_PREBUILTS
impedisce la pre-ottimizzazione dei predefiniti. Queste sono app che include $(BUILD_PREBUILT)
specificate nel loro Android.mk
. Saltare la pre-ottimizzazione delle app predefinite che potrebbero essere aggiornate tramite Google Play consente di risparmiare spazio nell'immagine di sistema ma si aggiunge al primo tempo di avvio. Tieni presente che questa opzione non ha effetto sulle app predefinite definite in Android.bp
.
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
specifica il filtro del compilatore predefinito per le applicazioni pre-ottimizzate. Queste app sono definite in Android.bp
o include $(BUILD_PREBUILT)
specificato nel loro Android.mk
. Se non specificato, il valore predefinito è speed-profile
oppure verify
se il valore non è specificato e non viene fornito un profilo.
L'abilitazione di WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
pre-ottimizza solo il percorso di classe di avvio e i jar del server di sistema.
La pre-ottimizzazione può anche essere abilitata o disabilitata su una singola app specificando l'opzione LOCAL_DEX_PREOPT
nella definizione del modulo. Questo può essere utile per disabilitare la pre-ottimizzazione delle app che potrebbero ricevere immediatamente gli aggiornamenti di Google Play poiché gli aggiornamenti renderebbero obsoleto il codice pre-ottimizzato nell'immagine di sistema. Ciò è utile anche per risparmiare spazio sulle OTA di aggiornamento delle versioni principali poiché gli utenti potrebbero già disporre di versioni più recenti delle app nella partizione dati.
LOCAL_DEX_PREOPT
supporta i valori 'true' o 'false' rispettivamente per abilitare o disabilitare la pre-ottimizzazione. Inoltre, è possibile specificare "nostripping" se la preottimizzazione non deve rimuovere il file classes.dex
dal file APK o JAR. Normalmente questo file viene rimosso poiché non è più necessario dopo la pre-ottimizzazione, ma quest'ultima opzione è necessaria per consentire alle firme APK di terze parti di rimanere valide.
Passa le opzioni a dex2oat
per controllare come viene compilata l'immagine di avvio. Può essere utilizzato per specificare elenchi di classi di immagini personalizzate, elenchi di classi compilati e filtri del compilatore.
Passa le opzioni a dex2oat
per controllare come viene compilato tutto tranne l'immagine di avvio.
Fornisce la possibilità di passare le opzioni dex2oat
per un modulo particolare e una configurazione del prodotto. Viene impostato nel file device.mk
di un prodotto da $(call add-product-dex-preopt-module-config,<modules>,<option>)
dove <modules>
è un elenco di nomi LOCAL_MODULE e LOCAL_PACKAGE per JAR e APK file, rispettivamente.
Elenco delle applicazioni che sono state identificate come core dei prodotti e che è opportuno compilare con il filtro del compilatore di speed
. Ad esempio, le app persistenti come SystemUI hanno la possibilità di utilizzare la compilazione guidata dal profilo solo al riavvio successivo, quindi potrebbe essere meglio per il prodotto avere queste app sempre compilate in AOT.
Elenco delle applicazioni caricate dal server di sistema. Queste applicazioni vengono compilate per impostazione predefinita con il filtro del compilatore di speed
.
Se includere una versione di debug di ART nel dispositivo. Per impostazione predefinita, questo è abilitato per userdebug e build eng. Il comportamento può essere ignorato impostando esplicitamente l'opzione su true
o false
.
Per impostazione predefinita, il dispositivo utilizza la versione non di debug ( libart.so
). Per cambiare, impostare la proprietà di sistema persist.sys.dalvik.vm.lib.2
su libartd.so
.
In Android 5.1.0 tramite Android 6.0.1, è possibile specificare WITH_DEXPREOPT_PIC
per abilitare il codice indipendente dalla posizione (PIC). Con questo, il codice compilato dall'immagine non deve essere riposizionato da /system in /data/dalvik-cache, risparmiando spazio nella partizione dati. Tuttavia, c'è un leggero impatto sul runtime perché disabilita un'ottimizzazione che sfrutta il codice dipendente dalla posizione. In genere, i dispositivi che desiderano risparmiare spazio in /data dovrebbero abilitare la compilazione PIC.
In Android 7.0, la compilazione PIC era abilitata per impostazione predefinita.
Questa opzione è stata sostituita con WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY che preopta anche i jar del server di sistema.
Questa opzione specifica il filtro del compilatore per il server di sistema.
Di seguito sono riportati elenchi di jar caricati dal server di sistema. I jar vengono compilati con il filtro del compilatore specificato da PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
Configurazione del percorso di classe di avvio
L'elenco delle classi precaricato è un elenco di classi che lo zigote inizializza all'avvio. Ciò evita a ciascuna app di dover eseguire questi inizializzatori di classe separatamente, consentendo loro di avviarsi più velocemente e condividere le pagine in memoria. Il file di elenco delle classi precaricato si trova in frameworks/base/config/preloaded-classes
per impostazione predefinita e contiene un elenco ottimizzato per l'uso tipico del telefono. Questo potrebbe essere diverso per altri dispositivi come i dispositivi indossabili e deve essere regolato di conseguenza. Fai attenzione quando sintonizza questo; l'aggiunta di troppe classi spreca memoria quando vengono caricate le classi non utilizzate. L'aggiunta di un numero troppo basso di classi costringe ogni app a dover avere la propria copia, il che, ancora una volta, spreca memoria.
Esempio di utilizzo (nel device.mk del prodotto):
PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
Nota: questa riga deve essere inserita prima di ereditare qualsiasi makefile di configurazione del prodotto che ottenga quello predefinito da: build/target/product/base.mk
Configurazione runtime
Opzioni Jit
Le seguenti opzioni influiscono sulle versioni Android solo in cui è disponibile il compilatore ART JIT.
- dalvik.vm.usejit: se la JIT è abilitata o meno.
- dalvik.vm.jitinitialsize (predefinito 64K): la capacità iniziale della cache del codice. La cache del codice sarà regolarmente GC e aumenterà se necessario.
- dalvik.vm.jitmaxsize (default 64M): la capacità massima della cache del codice.
- dalvik.vm.jitthreshold: (predefinito 10000) - Questa è la soglia che il contatore "hotness" di un metodo deve superare affinché il metodo venga compilato JIT. Il contatore "hotness" è una metrica interna al runtime. Include il numero di chiamate, rami arretrati e altri fattori.
- dalvik.vm.usejitprofiles: se i profili JIT sono abilitati o meno; questo può essere usato anche se dalvik.vm.usejit è falso. Si noti che se questo è falso, il
speed-profile
del filtro del compilatore non compila AOT alcun metodo ed equivale averify
. - dalvik.vm.jitprithreadweight (predefinito su dalvik.vm.jitthreshold / 20) - Il peso dei "campioni" JIT (vedi jitthreshold) per il thread dell'interfaccia utente dell'applicazione. Utilizzare per velocizzare la compilazione di metodi che influiscono direttamente sull'esperienza degli utenti durante l'interazione con l'app.
- dalvik.vm.jittransitionweight: (predefinito su dalvik.vm.jitthreshold / 10) il peso dell'invocazione del metodo che effettua la transizione tra il codice di compilazione e l'interprete. Questo aiuta ad assicurarsi che i metodi coinvolti siano compilati per ridurre al minimo le transizioni (che sono costose).
Opzioni di gestione dei pacchetti
A partire da Android 7.0, esiste un modo generico per specificare il livello di compilazione/verifica avvenuta nelle varie fasi. I livelli di compilazione possono essere configurati tramite le proprietà di sistema con i valori di default:
-
pm.dexopt.install=speed-profile
-
pm.dexopt.bg-dexopt=speed-profile
-
pm.dexopt.boot-after-ota=verify
-
pm.dexopt.first-boot=verify
Il filtro di compilazione per la prima volta il dispositivo si avvia. Il filtro qui utilizzato influisce solo sul tempo di avvio dopo la fabbrica. Si consiglia di
verify
il filtro per evitare lunghi tempi prima che un utente possa utilizzare il telefono per la prima volta. Si noti che se tutte le applicazioni nell'immagine di sistema sono già compilateverify
,speed-profile
ospeed
con il contesto del caricatore di classi corretto,pm.dexopt.first-boot
non avrà alcun effetto.
Questo è il filtro di compilazione utilizzato durante l'installazione di applicazioni tramite Google Play. Si consiglia di impostare il filtro di installazione su profilo di velocità per consentire l'utilizzo dei profili dai file di metadati dex. Si noti che se un profilo non viene fornito o se è vuoto, il profilo di velocità equivale a verificare.
Questo è il filtro di compilazione utilizzato quando il dispositivo è inattivo, in carica e completamente carico. Prova il filtro del compilatore del speed-profile
per sfruttare la compilazione guidata dal profilo e risparmiare spazio di archiviazione.
Il filtro di compilazione utilizzato dopo un aggiornamento over-the-air. Consigliamo vivamente il filtro di verify
del compilatore per questa opzione per evitare tempi di avvio molto lunghi.
Opzioni Dex2oat
Si noti che queste opzioni influiscono su dex2oat
durante la compilazione sul dispositivo e durante la pre-ottimizzazione, mentre la maggior parte delle opzioni discusse sopra interessa solo la pre-ottimizzazione.
Per controllare dex2oat
durante la compilazione dell'immagine di avvio:
- dalvik.vm.image-dex2oat-Xms: dimensione dell'heap iniziale
- dalvik.vm.image-dex2oat-Xmx: dimensione massima dell'heap
- dalvik.vm.image-dex2oat-filter: opzione del filtro del compilatore
- dalvik.vm.image-dex2oat-threads: numero di thread da utilizzare
Per controllare dex2oat
mentre compila tutto oltre all'immagine di avvio:
- dalvik.vm.dex2oat-Xms: dimensione heap iniziale
- dalvik.vm.dex2oat-Xmx: dimensione massima dell'heap
- dalvik.vm.dex2oat-filter: opzione del filtro del compilatore
Nelle versioni tramite Android 6.0, viene fornita un'opzione aggiuntiva per compilare tutto oltre all'immagine di avvio:
- dalvik.vm.dex2oat-threads: numero di thread da utilizzare
A partire da Android 6.1, questo diventa due opzioni aggiuntive per compilare tutto oltre all'immagine di avvio:
- dalvik.vm.boot-dex2oat-threads: numero di thread da utilizzare durante l'avvio
- dalvik.vm.dex2oat-threads: numero di thread da utilizzare dopo l'avvio
A partire da Android 7.1, sono disponibili due opzioni per controllare il modo in cui viene utilizzata la memoria durante la compilazione di qualsiasi cosa oltre all'immagine di avvio:
- dalvik.vm.dex2oat-very-large: dimensione minima totale del file dex in byte per disabilitare la compilazione AOT
- dalvik.vm.dex2oat-swap: usa il file di scambio dex2oat (per dispositivi con memoria insufficiente)
Le opzioni che controllano la dimensione dell'heap iniziale e massima per dex2oat
non dovrebbero essere ridotte poiché potrebbero limitare le applicazioni che possono essere compilate.
A partire da Android 11, vengono fornite tre opzioni di affinità della CPU per consentire di limitare i thread del compilatore a un gruppo specifico di CPU:
- dalvik.vm.boot-dex2oat-cpu-set: CPU che eseguono thread dex2oat durante l'avvio
- dalvik.vm.image-dex2oat-cpu-set: CPU che eseguono dex2oat durante la compilazione dell'immagine di avvio
- dalvik.vm.dex2oat-cpu-set: CPU che eseguono thread dex2oat dopo l'avvio
Le CPU devono essere specificate come un elenco separato da virgole di ID CPU. Ad esempio per eseguire su dex2oat sulle CPU 0-3, impostare:
dalvik.vm.dex2oat-cpu-set=0,1,2,3
Quando si impostano le proprietà di affinità della CPU, si consiglia di far corrispondere la proprietà corrispondente per il numero di thread dex2oat in modo che corrisponda al numero di CPU selezionate per evitare memoria non necessaria e conflitti di I/O:
dalvik.vm.dex2oat-cpu-set=0,1,2,3 dalvik.vm.dex2oat-threads=4
A partire da Android 12, sono state aggiunte le seguenti opzioni:
- dalvik.vm.ps-min-first-save-ms: il tempo di attesa che il runtime generi un profilo dell'applicazione, al primo avvio dell'applicazione
- dalvik.vm.ps-min-save-period-ms: il tempo minimo di attesa prima di aggiornare il profilo di un'app
- dalvik.vm.systemservercompilerfilter: il filtro del compilatore utilizzato dal dispositivo durante la ricompilazione del server di sistema
Configurazione specifica A/B
Configurazione ROM
A partire da Android 7.0, i dispositivi possono utilizzare due partizioni di sistema per abilitare gli aggiornamenti di sistema A/B . Per risparmiare sulla dimensione della partizione di sistema, i file preoptati possono essere installati nella seconda partizione di sistema inutilizzata. Vengono quindi copiati nella partizione dati al primo avvio.
Esempio di utilizzo (in device-common.mk
):
PRODUCT_PACKAGES += \ cppreopts.sh PRODUCT_PROPERTY_OVERRIDES += \ ro.cp_system_other_odex=1
E in BoardConfig.mk
del dispositivo:
BOARD_USES_SYSTEM_OTHER_ODEX := true
Si noti che il codice del percorso di classe di avvio, il codice del server di sistema e le applicazioni core specifiche del prodotto vengono sempre compilati nella partizione di sistema. Per impostazione predefinita, tutte le altre applicazioni vengono compilate nella seconda partizione di sistema inutilizzata. Questo può essere controllato con SYSTEM_OTHER_ODEX_FILTER
, che ha un valore predefinito di:
SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
Sfondo dexpt OTA
Con i dispositivi abilitati A/B, le applicazioni possono essere compilate in background per l'aggiornamento alla nuova immagine di sistema. Vedere Compilazione di app in background per includere facoltativamente lo script di compilazione e i file binari nell'immagine di sistema. Il filtro di compilazione utilizzato per questa compilazione è controllato con:
pm.dexopt.ab-ota=speed-profile
Si consiglia di utilizzare speed-profile
per sfruttare la compilazione guidata del profilo e risparmiare spazio di archiviazione.