Configuration de l'ART

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 :

  1. Une application est initialement installée sans aucune compilation AOT. Les premières fois que l'application s'exécute, elle sera interprétée et les méthodes fréquemment exécutées seront compilées JIT.
  2. 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.
  3. Le prochain redémarrage d'une application utilisera le code guidé par le profil et évitera de faire une compilation JIT au moment de l'exécution pour les méthodes déjà compilées. Les méthodes compilées JIT lors des nouvelles exécutions seront 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 O, 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 :

  1. Configuration de la ROM système : quel code est compilé par AOT lors de la création d'une image système.
  2. 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 O, il existe quatre filtres officiellement pris en charge :

  • vérifier : n'exécute que la vérification du code DEX.
  • quicken : exécutez la vérification du code DEX et optimisez certaines instructions DEX pour obtenir de meilleures performances de l'interpréteur.
  • vitesse : 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 /system 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 du compilateur rapide par défaut.
  • Code du serveur système : compilé avec le filtre du compilateur rapide par défaut.
  • Applications principales spécifiques au produit : compilées avec le filtre du compilateur de vitesse par défaut.
  • Toutes les autres applications : compilées avec le filtre du compilateur Quicken par défaut.

Options de makefile

  • WITH_DEXPREOPT
  • Indique si dex2oat est appelé sur le code DEX installé sur l'image système. Activé par défaut.

  • DONT_DEXPREOPT_PREBUILTS (depuis Android L)
  • 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 , comme Gmail. Ignorer la pré-optimisation des applications prédéfinies qui sont susceptibles d'être mises à jour via Google Play économise de l'espace /system , mais augmente le temps de premier démarrage.

  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER (depuis Android 9)
  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER spécifie le filtre de compilateur par défaut pour les applications pré-optimisées. Ce sont des applications qui include $(BUILD_PREBUILT) spécifié dans leur Android.mk , comme Gmail. Si elle n'est pas spécifiée, la valeur par défaut est quicken.

  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY (nouveau dans Android O MR1)
  • 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.

  • LOCAL_DEX_PREOPT
  • 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.

  • PRODUCT_DEX_PREOPT_BOOT_FLAGS
  • 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.

  • PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
  • Passe des options à dex2oat pour contrôler la manière dont tout ce qui n'est pas l'image de démarrage est compilé.

  • PRODUCT_DEX_PREOPT_MODULE_CONFIGS
  • 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>)<modules> est une liste de noms LOCAL_MODULE et LOCAL_PACKAGE pour JAR et APK fichiers, respectivement.

  • PRODUCT_DEXPREOPT_SPEED_APPS (New in Android O)
  • 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 rapide . 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.

  • PRODUCT_SYSTEM_SERVER_APPS (New in Android O)
  • Liste des applications chargées par le serveur système. Ces applications seront compilées par défaut avec le filtre du compilateur rapide .

  • PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(Post Android O)
  • 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 utilisera 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 .

  • WITH_DEXPREOPT_PIC (Removed in Android O)
  • 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.

  • WITH_DEXPREOPT_BOOT_IMG_ONLY (supprimé dans Android O MR1)
  • 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.

Configuration du chemin de classe de démarrage

  • Liste des classes préchargées
  • 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

  • Liste des classes d'images
  • La liste des classes d'images est une liste de classes que dex2oat initialise à l'avance et stocke dans le fichier boot.art. Cela permet au zygote de charger ces résultats à partir du fichier boot.art au démarrage au lieu d'exécuter les initialiseurs pour ces classes lui-même pendant le préchargement. Une caractéristique clé de ceci est que les pages chargées à partir de l'image et partagées entre les processus peuvent être propres, ce qui permet de les échanger facilement dans des situations à faible mémoire. Dans L, par défaut, la liste des classes d'images utilise la même liste que la liste des classes préchargées. À partir de la post-L dans AOSP, une liste de classes d'images personnalisées peut être spécifiée à l'aide de :

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Exemple d'utilisation (dans le device.mk du produit) :

    PRODUCT_DEX_PREOPT_BOOT_FLAGS += --image-classes=<filename>
    
  • Liste des classes compilées
  • Dans l'AOSP post-L, un sous-ensemble de classes du chemin de classe de démarrage peut être spécifié pour être compilé lors de la pré-optimisation à l'aide de la liste des classes compilées. Cela peut être une option utile pour les appareils dont l'espace est très restreint et qui ne peuvent pas contenir l'intégralité de l'image de démarrage pré-optimisée. Cependant, les classes de notes non spécifiées par cette liste ne seront pas compilées - pas même sur l'appareil - et doivent être interprétées, ce qui peut affecter les performances d'exécution. Par défaut, dex2oat recherchera une liste de classes compilées dans $OUT/system/etc/compiled-classes, afin qu'une liste personnalisée puisse être copiée à cet emplacement par le device.mk. Un emplacement de fichier particulier peut également être spécifié à l'aide de :

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Exemple d'utilisation (dans le device.mk du produit) :

    PRODUCT_COPY_FILES += <filename>:system/etc/compiled-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 profil de vitesse du filtre du compilateur ne compile aucune méthode AOT et équivaut à quicken .
  • 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
  • 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 à quicken.

  • pm.dexopt.bg-dexopt=speed-profile
  • 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 profil de vitesse pour tirer parti de la compilation guidée par profil et économiser sur le stockage.

  • pm.dexopt.boot=verify
  • Le filtre de compilation utilisé après une mise à jour en direct. Nous recommandons fortement le filtre de vérification du compilateur pour cette option afin d'éviter des temps de démarrage très longs.

  • pm.dexopt.first-boot=quicken
  • Le filtre de compilation pour la première fois que l'appareil démarre. Le filtre utilisé ici n'affectera que le temps de démarrage après l'usine. Nous recommandons d' accélérer le filtre pour éviter qu'un utilisateur n'utilise le téléphone pour la première fois. Notez que si toutes les applications dans /system sont déjà compilées avec le filtre du compilateur quicken ou sont compilées avec le filtre du compilateur speed ou speed-profile , pm.dexopt.first-boot n'a aucun effet.

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 utilisera 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.