Cette page explique comment configurer ART et ses options de compilation. Les sujets abordés ici incluent la configuration de la pré-compilation de l'image système, les options de compilation dex2oat et comment échanger l'espace de partition système, l'espace de partition de données et les performances.
Voir ART et Dalvik , le format exécutable Dalvik et les pages restantes sur source.android.com pour travailler avec ART. Consultez Vérification du comportement des applications sur Android Runtime (ART) pour vous assurer que vos applications fonctionnent correctement.
Comment fonctionne l'ART
ART utilise une compilation anticipée (AOT) et, à partir d'Android 7.0 (Nougat ou N), il utilise une combinaison hybride d'AOT, de compilation juste-à-temps (JIT) et de compilation guidée par profil. La combinaison de tous ces modes de compilation est configurable et sera abordée dans cette section. Par exemple, les appareils Pixel sont configurés avec le flux de compilation suivant :
- Une application est initialement installée sans aucune compilation AOT. Les premières fois que l'application s'exécute, elle est interprétée et les méthodes fréquemment exécutées sont compilées JIT.
- Lorsque l'appareil est inactif et en charge, un démon de compilation s'exécute pour compiler AOT le code fréquemment utilisé en fonction d'un profil généré lors des premières exécutions.
- Le prochain redémarrage d'une application utilise le code guidé par le profil et évite de faire une compilation JIT à l'exécution pour les méthodes déjà compilées. Les méthodes qui sont compilées JIT lors des nouvelles exécutions sont ajoutées au profil, qui sera ensuite récupéré par le démon de compilation.
ART comprend un compilateur (l'outil dex2oat
) et un runtime ( libart.so
) qui est chargé pour démarrer le Zygote. L'outil dex2oat
prend un fichier APK et génère un ou plusieurs fichiers d'artefact de compilation que le runtime charge. Le nombre de fichiers, leurs extensions et leurs noms sont susceptibles de changer d'une version à l'autre, mais à partir de la version Android 8, les fichiers générés sont :
-
.vdex
: contient le code DEX non compressé de l'APK, avec quelques métadonnées supplémentaires pour accélérer la vérification. -
.odex
: contient le code compilé AOT pour les méthodes dans l'APK. -
.art (optional)
: contient des représentations internes ART de certaines chaînes et classes répertoriées dans l'APK, utilisées pour accélérer le démarrage de l'application.
Options de compilation
Les options de compilation pour ART sont de deux catégories :
- Configuration de la ROM système : quel code est compilé par AOT lors de la création d'une image système.
- Configuration d'exécution : comment ART compile et exécute des applications sur un appareil.
L'une des principales options ART pour configurer ces deux catégories est les filtres du compilateur . Les filtres du compilateur déterminent la manière dont ART compile le code DEX et constituent une option transmise à l'outil dex2oat
. À partir d'Android 8, il existe quatre filtres officiellement pris en charge :
-
verify
: n'exécute que la vérification du code DEX. -
quicken
: (supprimé depuis Android 12) exécutez la vérification du code DEX et optimisez certaines instructions DEX pour obtenir de meilleures performances de l'interpréteur. -
speed
: exécutez la vérification du code DEX et compilez toutes les méthodes AOT. -
speed-profile
: exécute la vérification du code DEX et les méthodes de compilation AOT répertoriées dans un fichier de profil.
Configuration de la ROM système
Il existe un certain nombre d'options de construction ART disponibles pour configurer une ROM système. La configuration de ces options dépend de l'espace de stockage disponible pour l'image système et du nombre d'applications préinstallées. Les fichiers JAR/APK compilés dans une ROM système peuvent être divisés en quatre catégories :
- Code de chemin de classe de démarrage : compilé avec le filtre de compilateur
speed-profile
par défaut. - Code du serveur système (voir
PRODUCT_SYSTEM_SERVER_JARS
,PRODUCT_APEX_SYSTEM_SERVER_JARS
,PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
,PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
plus loin dans ce document) :- (depuis Android 14 (AOSP expérimental)) compilé avec le filtre du compilateur
speed-profile
par défaut, ou compilé avec le filtre du compilateur despeed
si aucun profil n'est fourni. - (jusqu'à Android 13) compilé avec le filtre du compilateur de
speed
par défaut.
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
(voir plus loin dans ce document). - (depuis Android 14 (AOSP expérimental)) compilé avec le filtre du compilateur
- Applications principales spécifiques au produit (voir
PRODUCT_DEXPREOPT_SPEED_APPS
plus loin dans ce document) : compilées avec le filtre du compilateur despeed
par défaut. - Toutes les autres applications : compilées avec le filtre de compilateur
speed-profile
par défaut, ou compilées avec le filtre de compilateur deverify
si aucun profil n'est fourni.Configurable via
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
(voir plus loin dans ce document).
Options de makefile
-
WITH_DEXPREOPT
-
DONT_DEXPREOPT_PREBUILTS
(depuis Android 5) -
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
(depuis Android 9) -
WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
(nouveau dans 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
(supprimé dans Android 8 MR1) -
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
- (depuis Android 14 (AOSP expérimental)) S'il n'est pas spécifié, le filtre du compilateur
speed-profile
est utilisé, ou le filtre du compilateur despeed
est utilisé si aucun profil n'est fourni. - (jusqu'à Android 13) S'il n'est pas spécifié, le filtre du compilateur de
speed
est utilisé. - S'il est défini sur
speed
, le filtre du compilateur despeed
est utilisé. - S'il est défini sur
speed-profile
, le filtre de compilateurspeed-profile
est utilisé, ou le filtre de compilateur deverify
est utilisé si aucun profil n'est fourni. - S'il est défini sur
verify
, le filtre du compilateur deverify
est utilisé. -
PRODUCT_SYSTEM_SERVER_JARS
,PRODUCT_APEX_SYSTEM_SERVER_JARS
,PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
,PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
- (obligatoire)
PRODUCT_SYSTEM_SERVER_JARS
: liste des fichiers jar de chemin de classe du serveur système sur la plate-forme (c'est-à-dire dans le cadre deSYSTEMSERVERCLASSPATH
). L'ajout de jars de chemin de classe de serveur système à cette liste est requis. Si vous ne parvenez pas à ajouter des jars de chemin de classe de serveur système à la liste, ces jars ne seront pas chargés. - (obligatoire)
PRODUCT_APEX_SYSTEM_SERVER_JARS
: liste des fichiers jar de chemin de classe du serveur système fournis via apex (c'est-à-dire dans le cadre deSYSTEMSERVERCLASSPATH
). Le format est<apex name>:<jar name>
. L'ajout de jars de chemin de classe de serveur système apex à cette liste est requis. Si vous ne parvenez pas à ajouter des fichiers JAR de chemin de classe de serveur système Apex à cette liste, ces fichiers JAR ne seront pas chargés. - (facultatif, depuis Android 13)
PRODUCT_STANDALONE_SYSTEM_SERVER_JARS
: Liste des jars que le serveur système charge dynamiquement à l'aide de classloaders séparés (viaSystemServiceManager.startServiceFromJar
). L'ajout de jars de serveur système autonome à cette liste n'est pas obligatoire mais fortement recommandé car cela rend les jars compilés et a donc de bonnes performances d'exécution. - (requis, depuis Android 13)
PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
: liste des jars fournis via apex que le serveur système charge dynamiquement à l'aide de classloaders séparés (c'est-à-dire viaSystemServiceManager.startServiceFromJar
ou déclarés comme<apex-system-service>
). Le format est<apex name>:<jar name>
. L'ajout de fichiers JAR de serveur de système Apex autonomes à cette liste est requis. Le fait de ne pas ajouter de fichiers JAR de serveur de système Apex autonomes à cette liste entraîne un échec de démarrage. - Liste des classes préchargées
Indique si dex2oat
est appelé sur le code DEX installé sur l'image système. Activé par défaut.
L'activation DONT_DEXPREOPT_PREBUILTS
empêche les pré-construits d'être pré-optimisés. Ce sont des applications qui include $(BUILD_PREBUILT)
spécifié dans leur Android.mk
. Ignorer la pré-optimisation des applications prédéfinies susceptibles d'être mises à jour via Google Play permet d'économiser de l'espace dans l'image système, mais augmente le temps de premier démarrage. Notez que cette option n'a aucun effet sur les applications prédéfinies définies dans Android.bp
.
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
spécifie le filtre de compilateur par défaut pour les applications pré-optimisées. Ces applications sont définies dans Android.bp
ou include $(BUILD_PREBUILT)
spécifié dans leur Android.mk
. Si elle n'est pas spécifiée, la valeur par défaut est speed-profile
, ou verify
si la valeur n'est pas spécifiée et qu'aucun profil n'est fourni.
L'activation WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
pré-optimise uniquement le chemin de classe de démarrage et les jars du serveur système.
La pré-optimisation peut également être activée ou désactivée sur une base d'application individuelle en spécifiant l'option LOCAL_DEX_PREOPT
dans la définition du module. Cela peut être utile pour désactiver la pré-optimisation des applications susceptibles de recevoir immédiatement les mises à jour de Google Play, car les mises à jour rendraient obsolète le code pré-optimisé dans l'image système. Ceci est également utile pour économiser de l'espace sur les OTA de mise à niveau de version majeure, car les utilisateurs peuvent déjà disposer de versions plus récentes d'applications dans la partition de données.
LOCAL_DEX_PREOPT
prend en charge les valeurs 'true' ou 'false' pour activer ou désactiver la pré-optimisation, respectivement. De plus, "nostripping" peut être spécifié si la pré-optimisation ne doit pas supprimer le fichier classes.dex
du fichier APK ou JAR. Normalement, ce fichier est supprimé car il n'est plus nécessaire après la pré-optimisation, mais cette dernière option est nécessaire pour permettre aux signatures APK tierces de rester valides.
Passe des options à dex2oat
pour contrôler la façon dont l'image de démarrage est compilée. Il peut être utilisé pour spécifier des listes de classes d'images personnalisées, des listes de classes compilées et des filtres de compilateur.
Passe des options à dex2oat
pour contrôler la manière dont tout ce qui n'est pas l'image de démarrage est compilé.
Fournit la possibilité de transmettre les options dex2oat
pour une configuration de module et de produit particulière. Il est défini dans le fichier device.mk
d'un produit par $(call add-product-dex-preopt-module-config,<modules>,<option>)
où <modules>
est une liste de noms LOCAL_MODULE et LOCAL_PACKAGE pour JAR et APK fichiers, respectivement.
Liste des applications qui ont été identifiées comme étant au cœur des produits et qu'il est souhaitable de compiler avec le filtre du compilateur speed
. Par exemple, les applications persistantes telles que SystemUI ont la possibilité d'utiliser la compilation guidée par profil uniquement au prochain redémarrage, il peut donc être préférable pour le produit que ces applications soient toujours compilées par AOT.
Liste des applications chargées par le serveur système. Ces applications sont compilées par défaut avec le filtre du compilateur speed
.
S'il faut inclure une version de débogage d'ART sur l'appareil. Par défaut, ceci est activé pour les builds userdebug et eng. Le comportement peut être remplacé en définissant explicitement l'option sur true
ou false
.
Par défaut, l'appareil utilise la version non déboguée ( libart.so
). Pour basculer, définissez la propriété système persist.sys.dalvik.vm.lib.2
sur libartd.so
.
Dans Android 5.1.0 à Android 6.0.1, WITH_DEXPREOPT_PIC
peut être spécifié pour activer le code indépendant de la position (PIC). Avec cela, le code compilé à partir de l'image n'a pas besoin d'être déplacé de /system vers /data/dalvik-cache, ce qui permet d'économiser de l'espace dans la partition de données. Cependant, il y a un léger impact sur l'exécution car il désactive une optimisation qui tire parti du code dépendant de la position. En règle générale, les périphériques souhaitant économiser de l'espace dans /data doivent activer la compilation PIC.
Dans Android 7.0, la compilation PIC était activée par défaut.
Cette option a été remplacée par WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY qui préopte également les jars du serveur système.
Cette option spécifie le filtre du compilateur pour le serveur système.
Voici les listes de fichiers JAR chargés par le serveur système. Les jars sont compilés avec le filtre du compilateur spécifié par PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
Configuration du chemin de classe de démarrage
La liste des classes préchargées est une liste de classes que le zygote initialise au démarrage. Cela évite à chaque application d'avoir à exécuter ces initialiseurs de classe séparément, ce qui leur permet de démarrer plus rapidement et de partager des pages en mémoire. Le fichier de liste des classes préchargées se trouve par défaut dans frameworks/base/config/preloaded-classes
et contient une liste adaptée à une utilisation typique du téléphone. Cela peut être différent pour d'autres appareils tels que les appareils portables et doit être réglé en conséquence. Soyez prudent lorsque vous réglez cela; ajouter trop de classes gaspille de la mémoire lorsque les classes inutilisées sont chargées. Ajouter trop peu de classes oblige chaque application à avoir sa propre copie, ce qui, encore une fois, gaspille de la mémoire.
Exemple d'utilisation (dans le fichier device.mk du produit) :
PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
Remarque : Cette ligne doit être placée avant d'hériter de tout fichier makefile de configuration de produit qui obtient celui par défaut à partir de : build/target/product/base.mk
Configuration d'exécution
Options de jit
Les options suivantes affectent les versions d'Android uniquement lorsque le compilateur ART JIT est disponible.
- dalvik.vm.usejit : si le JIT est activé ou non.
- dalvik.vm.jitinitialsize (64K par défaut) : la capacité initiale du cache de code. Le code cache va régulièrement GC et augmenter si besoin.
- dalvik.vm.jitmaxsize (64M par défaut) : la capacité maximale du cache de code.
- dalvik.vm.jitthreshold : (par défaut 10000) - Il s'agit du seuil que le compteur "hotness" d'une méthode doit franchir pour que la méthode soit compilée JIT. Le compteur "hotness" est une métrique interne au runtime. Il comprend le nombre d'appels, les branchements en amont et d'autres facteurs.
- dalvik.vm.usejitprofiles : si les profils JIT sont activés ou non ; ceci peut être utilisé même si dalvik.vm.usejit est faux. Notez que si cela est faux, le
speed-profile
du filtre du compilateur ne compile aucune méthode AOT et équivaut àverify
. - dalvik.vm.jitprithreadweight (valeur par défaut dalvik.vm.jitthreshold / 20) - Le poids des "échantillons" JIT (voir jitthreshold) pour le thread d'interface utilisateur de l'application. Utilisez-le pour accélérer la compilation des méthodes qui affectent directement l'expérience des utilisateurs lors de l'interaction avec l'application.
- dalvik.vm.jittransitionweight : (par défaut à dalvik.vm.jitthreshold / 10) le poids de l'invocation de la méthode qui fait la transition entre le code compilé et l'interpréteur. Cela permet de s'assurer que les méthodes impliquées sont compilées pour minimiser les transitions (qui sont coûteuses).
Options du gestionnaire de packages
Depuis Android 7.0, il existe un moyen générique de spécifier le niveau de compilation/vérification qui s'est produit à différentes étapes. Les niveaux de compilation peuvent être configurés via les propriétés système, les valeurs par défaut étant :
-
pm.dexopt.install=speed-profile
-
pm.dexopt.bg-dexopt=speed-profile
-
pm.dexopt.boot-after-ota=verify
-
pm.dexopt.first-boot=verify
Le filtre de compilation pour la première fois que l'appareil démarre. Le filtre utilisé ici n'affecte que le temps de démarrage après l'usine. Nous vous recommandons de
verify
le filtre pour éviter de longs délais avant qu'un utilisateur puisse utiliser le téléphone pour la toute première fois. Notez que si toutes les applications de l'image système sont déjà compilées avecverify
,speed-profile
ouspeed
avec le bon contexte de chargeur de classe,pm.dexopt.first-boot
n'aura aucun effet.
Il s'agit du filtre de compilation utilisé lors de l'installation d'applications via Google Play. Nous vous recommandons de définir le filtre d'installation sur speed-profile afin de permettre l'utilisation de profils à partir des fichiers de métadonnées dex. Notez que si un profil n'est pas fourni ou s'il est vide, speed-profile équivaut à vérifier.
Il s'agit du filtre de compilation utilisé lorsque l'appareil est inactif, en charge et complètement chargé. Essayez le filtre de compilateur de speed-profile
pour tirer parti de la compilation guidée par profil et économiser sur le stockage.
Le filtre de compilation utilisé après une mise à jour en direct. Nous recommandons fortement le filtre de verify
du compilateur pour cette option afin d'éviter des temps de démarrage très longs.
Options Dex2oat
Notez que ces options affectent dex2oat
lors de la compilation sur l'appareil ainsi que lors de la pré-optimisation, alors que la plupart des options décrites ci-dessus n'affectent que la pré-optimisation.
Pour contrôler dex2oat
pendant la compilation de l'image de démarrage :
- dalvik.vm.image-dex2oat-Xms : taille initiale du tas
- dalvik.vm.image-dex2oat-Xmx : taille maximale du segment de mémoire
- dalvik.vm.image-dex2oat-filter : option de filtre du compilateur
- dalvik.vm.image-dex2oat-threads : nombre de threads à utiliser
Pour contrôler dex2oat
pendant qu'il compile tout sauf l'image de démarrage :
- dalvik.vm.dex2oat-Xms : taille initiale du tas
- dalvik.vm.dex2oat-Xmx : taille maximale du segment de mémoire
- dalvik.vm.dex2oat-filter : option de filtre du compilateur
Sur les versions jusqu'à Android 6.0, une option supplémentaire est fournie pour tout compiler en plus de l'image de démarrage :
- dalvik.vm.dex2oat-threads : nombre de threads à utiliser
À partir d'Android 6.1, cela devient deux options supplémentaires pour tout compiler en plus de l'image de démarrage :
- dalvik.vm.boot-dex2oat-threads : nombre de threads à utiliser au démarrage
- dalvik.vm.dex2oat-threads : nombre de threads à utiliser après le démarrage
À partir d'Android 7.1, deux options sont fournies pour contrôler l'utilisation de la mémoire lors de la compilation de tout en dehors de l'image de démarrage :
- dalvik.vm.dex2oat-very-large : taille minimale totale du fichier dex en octets pour désactiver la compilation AOT
- dalvik.vm.dex2oat-swap : utilisez le fichier d'échange dex2oat (pour les appareils à faible mémoire)
Les options qui contrôlent la taille de tas initiale et maximale pour dex2oat
ne doivent pas être réduites car elles pourraient limiter les applications pouvant être compilées.
À partir d'Android 11, trois options d'affinité CPU sont fournies pour permettre aux threads du compilateur d'être limités à un groupe spécifique de CPU :
- dalvik.vm.boot-dex2oat-cpu-set : processeurs exécutant des threads dex2oat au démarrage
- dalvik.vm.image-dex2oat-cpu-set : processeurs exécutant dex2oat lors de la compilation de l'image de démarrage
- dalvik.vm.dex2oat-cpu-set : processeurs exécutant des threads dex2oat après le démarrage
Les processeurs doivent être spécifiés sous la forme d'une liste d'ID de processeur séparés par des virgules. Par exemple, pour exécuter sur dex2oat sur les CPU 0-3, définissez :
dalvik.vm.dex2oat-cpu-set=0,1,2,3
Lors de la définition des propriétés d'affinité du processeur, nous vous recommandons de faire correspondre la propriété correspondante pour que le nombre de threads dex2oat corresponde au nombre de processeurs sélectionnés afin d'éviter les conflits de mémoire et d'E/S inutiles :
dalvik.vm.dex2oat-cpu-set=0,1,2,3 dalvik.vm.dex2oat-threads=4
À partir d'Android 12, les options suivantes ont été ajoutées :
- dalvik.vm.ps-min-first-save-ms : le temps d'attente pour que le runtime génère un profil de l'application, la première fois que l'application est lancée
- dalvik.vm.ps-min-save-period-ms : le temps minimum à attendre avant de mettre à jour le profil d'une app
- dalvik.vm.systemservercompilerfilter : le filtre du compilateur que l'appareil utilise lors de la recompilation du serveur système
Configuration spécifique A/B
Configuration de la ROM
À partir d'Android 7.0, les appareils peuvent utiliser deux partitions système pour activer les mises à jour système A/B . Pour économiser sur la taille de la partition système, les fichiers préoptés peuvent être installés dans la deuxième partition système inutilisée. Ils sont ensuite copiés sur la partition de données au premier démarrage.
Exemple d'utilisation (dans device-common.mk
):
PRODUCT_PACKAGES += \ cppreopts.sh PRODUCT_PROPERTY_OVERRIDES += \ ro.cp_system_other_odex=1
Et dans BoardConfig.mk
de l'appareil :
BOARD_USES_SYSTEM_OTHER_ODEX := true
Notez que le code du chemin d'accès aux classes de démarrage, le code du serveur système et les applications principales spécifiques au produit sont toujours compilés sur la partition système. Par défaut, toutes les autres applications sont compilées sur la deuxième partition système inutilisée. Cela peut être contrôlé avec le SYSTEM_OTHER_ODEX_FILTER
, qui a une valeur par défaut de :
SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
Arrière-plan dexopt OTA
Avec les appareils compatibles A/B, les applications peuvent être compilées en arrière-plan pour la mise à jour vers la nouvelle image système. Voir Compilation d'applications en arrière-plan pour inclure éventuellement le script de compilation et les fichiers binaires dans l'image système. Le filtre de compilation utilisé pour cette compilation est contrôlé avec :
pm.dexopt.ab-ota=speed-profile
Nous vous recommandons d'utiliser speed-profile
pour tirer parti de la compilation guidée par profil et économiser sur le stockage.