Configuración de ART

Esta página explica cómo configurar ART y sus opciones de compilación. Los temas tratados aquí incluyen la configuración de la precompilación de la imagen del sistema, las opciones de compilación de dex2oat y cómo compensar el espacio de partición del sistema, el espacio de partición de datos y el rendimiento.

Consulte ART y Dalvik , el formato ejecutable de Dalvik y las páginas restantes en source.android.com para trabajar con ART. Consulte Verificación del comportamiento de la aplicación en Android Runtime (ART) para asegurarse de que sus aplicaciones funcionen correctamente.

Cómo funciona el ART

ART usa compilación anticipada (AOT) y, a partir de Android 7.0 (Nougat o N), usa una combinación híbrida de AOT, compilación justo a tiempo (JIT) y compilación guiada por perfil. La combinación de todos estos modos de compilación es configurable y se discutirá en esta sección. Como ejemplo, los dispositivos Pixel se configuran con el siguiente flujo de compilación:

  1. Una aplicación se instala inicialmente sin ninguna compilación AOT. Las primeras veces que se ejecuta la aplicación, se interpretará y los métodos que se ejecutan con frecuencia se compilarán JIT.
  2. Cuando el dispositivo está inactivo y cargándose, un demonio de compilación se ejecuta para compilar AOT el código de uso frecuente en función de un perfil generado durante las primeras ejecuciones.
  3. El próximo reinicio de una aplicación utilizará el código guiado por perfil y evitará realizar la compilación JIT en tiempo de ejecución para los métodos ya compilados. Los métodos que se compilan con JIT durante las nuevas ejecuciones se agregarán al perfil, que luego será seleccionado por el demonio de compilación.

ART comprende un compilador (la herramienta dex2oat ) y un tiempo de ejecución ( libart.so ) que se carga para iniciar Zygote. La herramienta dex2oat toma un archivo APK y genera uno o más archivos de artefactos de compilación que carga el tiempo de ejecución. La cantidad de archivos, sus extensiones y nombres están sujetos a cambios entre los lanzamientos, pero a partir del lanzamiento de Android O, los archivos que se generan son:

  • .vdex : contiene el código DEX sin comprimir del APK, con algunos metadatos adicionales para acelerar la verificación.
  • .odex : contiene código compilado AOT para métodos en el APK.
  • .art (optional) : contiene representaciones internas ART de algunas cadenas y clases enumeradas en el APK, que se utilizan para acelerar el inicio de la aplicación.

Opciones de compilación

Las opciones de compilación para ART son de dos categorías:

  1. Configuración de la ROM del sistema: qué código se compila AOT al crear una imagen del sistema.
  2. Configuración de tiempo de ejecución: cómo ART compila y ejecuta aplicaciones en un dispositivo.

Una opción básica de ART para configurar estas dos categorías son los filtros del compilador . Los filtros del compilador controlan cómo ART compila el código DEX y es una opción que se pasa a la herramienta dex2oat . A partir de Android O, hay cuatro filtros admitidos oficialmente:

  • verificar : solo ejecuta la verificación del código DEX.
  • acelerar : ejecute la verificación del código DEX y optimice algunas instrucciones DEX para obtener un mejor rendimiento del intérprete.
  • velocidad : ejecute la verificación del código DEX y AOT-compile todos los métodos.
  • perfil de velocidad : ejecuta la verificación del código DEX y los métodos de compilación AOT enumerados en un archivo de perfil.

Configuración de la ROM del sistema

Hay una serie de opciones de creación de ART disponibles para configurar una ROM del sistema. La forma de configurar estas opciones depende del espacio de almacenamiento disponible para /system y la cantidad de aplicaciones preinstaladas. Los JAR/APK que se compilan en una ROM del sistema se pueden dividir en cuatro categorías:

  • Código de classpath de arranque: compilado con el filtro del compilador de velocidad de forma predeterminada.
  • Código del servidor del sistema: compilado con el filtro del compilador de velocidad por defecto.
  • Aplicaciones principales específicas del producto: compiladas con el filtro del compilador de velocidad de forma predeterminada.
  • Todas las demás aplicaciones: compiladas con el filtro del compilador quicken de forma predeterminada.

Opciones de archivo MAKE

  • WITH_DEXPREOPT
  • Si se invoca dex2oat en el código DEX instalado en la imagen del sistema. Habilitado por defecto.

  • DONT_DEXPREOPT_PREBUILTS (desde Android L)
  • Habilitar DONT_DEXPREOPT_PREBUILTS evita que las compilaciones previas se optimicen previamente. Estas son aplicaciones que include $(BUILD_PREBUILT) especificado en su Android.mk , como Gmail. Omitir la optimización previa de las aplicaciones prediseñadas que probablemente se actualicen a través de Google Play ahorra espacio en el /system , pero aumenta el tiempo de primer arranque.

  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER (desde Android 9)
  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER especifica el filtro de compilador predeterminado para aplicaciones optimizadas previamente. Estas son aplicaciones que include $(BUILD_PREBUILT) especificado en su Android.mk , como Gmail. Si no se especifica, el valor predeterminado es acelerar.

  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY (nuevo en Android O MR1)
  • Habilitar WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY optimiza previamente solo el classpath de arranque y los archivos jar del servidor del sistema.

  • LOCAL_DEX_PREOPT
  • La optimización previa también se puede habilitar o deshabilitar en una aplicación individual especificando la opción LOCAL_DEX_PREOPT en la definición del módulo. Esto puede ser útil para deshabilitar la optimización previa de aplicaciones que pueden recibir actualizaciones de Google Play de inmediato, ya que las actualizaciones dejarían obsoleto el código optimizado previamente en la imagen del sistema. Esto también es útil para ahorrar espacio en las OTA de actualización de versiones principales, ya que es posible que los usuarios ya tengan versiones más nuevas de aplicaciones en la partición de datos.

    LOCAL_DEX_PREOPT admite los valores "verdadero" o "falso" para habilitar o deshabilitar la optimización previa, respectivamente. Además, se puede especificar 'nostripping' si la optimización previa no debe eliminar el archivo classes.dex del archivo APK o JAR. Normalmente, este archivo se elimina porque ya no es necesario después de la optimización previa, pero esta última opción es necesaria para permitir que las firmas de APK de terceros sigan siendo válidas.

  • PRODUCT_DEX_PREOPT_BOOT_FLAGS
  • Pasa opciones a dex2oat para controlar cómo se compila la imagen de arranque. Se puede usar para especificar listas de clases de imágenes personalizadas, listas de clases compiladas y filtros de compilador.

  • PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
  • Pasa opciones a dex2oat para controlar cómo se compila todo, además de la imagen de arranque.

  • PRODUCT_DEX_PREOPT_MODULE_CONFIGS
  • Brinda la capacidad de pasar opciones de dex2oat para un módulo y una configuración de producto en particular. Se establece en el archivo device.mk de un producto mediante $(call add-product-dex-preopt-module-config,<modules>,<option>) donde <modules> es una lista de nombres LOCAL_MODULE y LOCAL_PACKAGE para JAR y APK archivos, respectivamente.

  • PRODUCT_DEXPREOPT_SPEED_APPS (New in Android O)
  • Lista de aplicaciones que se han identificado como fundamentales para los productos y que es deseable compilar con el filtro del compilador de velocidad . Por ejemplo, las aplicaciones persistentes como SystemUI tienen la oportunidad de usar la compilación guiada por perfil solo en el próximo reinicio, por lo que puede ser mejor para el producto tener estas aplicaciones siempre compiladas con AOT.

  • PRODUCT_SYSTEM_SERVER_APPS (New in Android O)
  • Lista de aplicaciones que carga el servidor del sistema. Estas aplicaciones se compilarán de forma predeterminada con el filtro del compilador de velocidad .

  • PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(Post Android O)
  • Si incluir una versión de depuración de ART en el dispositivo. De forma predeterminada, esto está habilitado para compilaciones de depuración de usuarios y eng. El comportamiento se puede anular estableciendo explícitamente la opción en true o false .

    De forma predeterminada, el dispositivo utilizará la versión sin depuración ( libart.so ). Para cambiar, establezca la propiedad del sistema persist.sys.dalvik.vm.lib.2 en libartd.so .

  • WITH_DEXPREOPT_PIC (Removed in Android O)
  • En Android 5.1.0 a Android 6.0.1, se puede especificar WITH_DEXPREOPT_PIC para habilitar el código independiente de la posición (PIC). Con esto, el código compilado de la imagen no tiene que ser reubicado de /system a /data/dalvik-cache, ahorrando espacio en la partición de datos. Sin embargo, hay un ligero impacto en el tiempo de ejecución porque deshabilita una optimización que aprovecha el código dependiente de la posición. Por lo general, los dispositivos que desean ahorrar espacio en /data deben habilitar la compilación de PIC.

    En Android 7.0, la compilación de PIC estaba habilitada de forma predeterminada.

  • WITH_DEXPREOPT_BOOT_IMG_ONLY (eliminado en Android O MR1)
  • Esta opción se reemplazó con WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY que también preopta los archivos jar del servidor del sistema.

Configuración de classpath de arranque

  • Lista de clases precargadas
  • La lista de clases precargadas es una lista de clases que el cigoto inicializa al iniciarse. Esto evita que cada aplicación tenga que ejecutar estos inicializadores de clase por separado, lo que les permite iniciarse más rápido y compartir páginas en la memoria. El archivo de la lista de clases precargadas se encuentra en frameworks/base/config/preloaded-classes de forma predeterminada y contiene una lista que está ajustada para el uso típico del teléfono. Esto puede ser diferente para otros dispositivos, como dispositivos portátiles, y debe ajustarse en consecuencia. Tenga cuidado al afinar esto; agregar demasiadas clases desperdicia memoria cuando se cargan clases no utilizadas. Agregar muy pocas clases obliga a cada aplicación a tener su propia copia, lo que de nuevo desperdicia memoria.

    Ejemplo de uso (en el dispositivo del producto.mk):

    PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
    

    Nota: Esta línea debe colocarse antes de heredar cualquier archivo MAKE de configuración del producto que obtenga el predeterminado de: build/target/product/base.mk

  • Lista de clases de imágenes
  • La lista de clases de imágenes es una lista de clases que dex2oat inicializa con anticipación y almacena en el archivo boot.art. Esto permite que el cigoto cargue estos resultados desde el archivo boot.art al inicio en lugar de ejecutar los inicializadores para estas clases durante la precarga. Una característica clave de esto es que las páginas cargadas desde la imagen y compartidas entre procesos pueden estar limpias, lo que permite intercambiarlas fácilmente en situaciones de poca memoria. En L, de forma predeterminada, la lista de clases de imágenes utiliza la misma lista que la lista de clases precargada. Comenzando después de L en AOSP, se puede especificar una lista de clases de imágenes personalizadas usando:

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Ejemplo de uso (en device.mk del producto):

    PRODUCT_DEX_PREOPT_BOOT_FLAGS += --image-classes=<filename>
    
  • Lista de Clases Compiladas
  • En el AOSP posterior a L, se puede especificar que se compile un subconjunto de clases del classpath de arranque durante la optimización previa mediante la lista de clases compiladas. Esta puede ser una opción útil para los dispositivos que tienen poco espacio y no pueden adaptarse a toda la imagen de arranque preoptimizada. Sin embargo, las clases de notas no especificadas en esta lista no se compilarán, ni siquiera en el dispositivo, y deben interpretarse, lo que podría afectar el rendimiento del tiempo de ejecución. De forma predeterminada, dex2oat buscará una lista de clases compiladas en $OUT/system/etc/compiled-classes, por lo que device.mk puede copiar una personalizada en esa ubicación. También se puede especificar una ubicación de archivo particular usando:

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Ejemplo de uso (en device.mk del producto):

    PRODUCT_COPY_FILES += <filename>:system/etc/compiled-classes
    

    Nota: Esta línea debe colocarse antes de heredar cualquier archivo MAKE de configuración del producto que obtenga el predeterminado de: build/target/product/base.mk

Configuración del tiempo de ejecución

Opciones de Jit

Las siguientes opciones afectan a las versiones de Android solo donde está disponible el compilador ART JIT.

  • dalvik.vm.usejit: si el JIT está habilitado o no.
  • dalvik.vm.jitinitialsize (predeterminado 64K): la capacidad inicial del caché de código. El caché de código se analizará regularmente y aumentará si es necesario.
  • dalvik.vm.jitmaxsize (predeterminado 64M): la capacidad máxima del caché de código.
  • dalvik.vm.jitthreshold: (predeterminado 10000): este es el umbral que el contador de "calor" de un método debe pasar para que el método se compile JIT. El contador de "calor" es una métrica interna del tiempo de ejecución. Incluye el número de llamadas, bifurcaciones hacia atrás y otros factores.
  • dalvik.vm.usejitprofiles: si los perfiles JIT están habilitados o no; esto se puede usar incluso si dalvik.vm.usejit es falso. Tenga en cuenta que si esto es falso, el perfil de velocidad del filtro del compilador no compila ningún método AOT y es equivalente a acelerar .
  • dalvik.vm.jitprithreadweight (predeterminado en dalvik.vm.jitthreshold / 20): el peso de las "muestras" JIT (consulte jitthreshold) para el subproceso de la interfaz de usuario de la aplicación. Úselo para acelerar la compilación de métodos que afectan directamente la experiencia de los usuarios cuando interactúan con la aplicación.
  • dalvik.vm.jittransitionweight: (predeterminado en dalvik.vm.jitthreshold / 10) el peso de la invocación del método que realiza la transición entre el código de compilación y el intérprete. Esto ayuda a garantizar que los métodos involucrados se compilen para minimizar las transiciones (que son costosas).

Opciones del administrador de paquetes

Desde Android 7.0, existe una forma genérica de especificar el nivel de compilación/verificación que ocurrió en varias etapas. Los niveles de compilación se pueden configurar a través de las propiedades del sistema con los valores predeterminados:

  • pm.dexopt.install=speed-profile
  • Este es el filtro de compilación utilizado al instalar aplicaciones a través de Google Play. Recomendamos que el filtro de instalación se establezca en perfil de velocidad para habilitar el uso de perfiles de los archivos de metadatos dex. Tenga en cuenta que si no se proporciona un perfil o si está vacío, el perfil de velocidad es equivalente a acelerar.

  • pm.dexopt.bg-dexopt=speed-profile
  • Este es el filtro de compilación que se usa cuando el dispositivo está inactivo, cargándose y completamente cargado. Pruebe el filtro del compilador de perfil de velocidad para aprovechar la compilación guiada por perfil y ahorrar en almacenamiento.

  • pm.dexopt.boot=verify
  • El filtro de compilación utilizado después de una actualización inalámbrica. Recomendamos encarecidamente el filtro del compilador de verificación para esta opción para evitar tiempos de arranque muy largos.

  • pm.dexopt.first-boot=quicken
  • El filtro de compilación por primera vez que arranca el dispositivo. El filtro utilizado aquí solo afectará el tiempo de arranque después de la fábrica. Recomendamos el filtro quicken para evitar mucho tiempo antes de que un usuario use el teléfono por primera vez. Tenga en cuenta que si todas las aplicaciones en /system ya están compiladas con el filtro del compilador quicken o están compiladas con el filtro del compilador speed o speed-profile , pm.dexopt.first-boot no tiene efecto.

Opciones de Dex2oat

Tenga en cuenta que estas opciones afectan a dex2oat durante la compilación en el dispositivo, así como durante la optimización previa, mientras que la mayoría de las opciones discutidas anteriormente afectan solo a la optimización previa.

Para controlar dex2oat mientras compila la imagen de arranque:

  • dalvik.vm.image-dex2oat-Xms: tamaño de almacenamiento dinámico inicial
  • dalvik.vm.image-dex2oat-Xmx: tamaño máximo de almacenamiento dinámico
  • dalvik.vm.image-dex2oat-filter: opción de filtro del compilador
  • dalvik.vm.image-dex2oat-threads: número de subprocesos a utilizar

Para controlar dex2oat mientras compila todo además de la imagen de arranque:

  • dalvik.vm.dex2oat-Xms: tamaño de almacenamiento dinámico inicial
  • dalvik.vm.dex2oat-Xmx: tamaño máximo de almacenamiento dinámico
  • dalvik.vm.dex2oat-filter: opción de filtro del compilador

En los lanzamientos hasta Android 6.0, se proporciona una opción adicional para compilar todo además de la imagen de arranque:

  • dalvik.vm.dex2oat-threads: número de subprocesos a utilizar

A partir de Android 6.1, esto se convierte en dos opciones adicionales para compilar todo además de la imagen de arranque:

  • dalvik.vm.boot-dex2oat-threads: número de subprocesos a usar durante el tiempo de arranque
  • dalvik.vm.dex2oat-threads: número de subprocesos para usar después del tiempo de arranque

A partir de Android 7.1, se proporcionan dos opciones para controlar cómo se usa la memoria al compilar todo, además de la imagen de arranque:

  • dalvik.vm.dex2oat-very-large: tamaño mínimo total del archivo dex en bytes para deshabilitar la compilación AOT
  • dalvik.vm.dex2oat-swap: use el archivo de intercambio dex2oat (para dispositivos con poca memoria)

Las opciones que controlan el tamaño de almacenamiento dinámico inicial y máximo para dex2oat no deben reducirse, ya que podrían limitar las aplicaciones que se pueden compilar.

A partir de Android 11, se proporcionan tres opciones de afinidad de CPU para permitir que los subprocesos del compilador se restrinjan a un grupo específico de CPU:

  • dalvik.vm.boot-dex2oat-cpu-set: CPU que ejecutan subprocesos dex2oat durante el arranque
  • dalvik.vm.image-dex2oat-cpu-set: CPU que ejecutan dex2oat mientras compilan la imagen de arranque
  • dalvik.vm.dex2oat-cpu-set: CPU que ejecutan subprocesos dex2oat después del tiempo de arranque

Las CPU deben especificarse como una lista separada por comas de ID de CPU. Por ejemplo, para ejecutar dex2oat en las CPU 0-3, configure:

dalvik.vm.dex2oat-cpu-set=0,1,2,3

Al configurar las propiedades de afinidad de la CPU, recomendamos hacer coincidir la propiedad correspondiente para la cantidad de subprocesos dex2oat para que coincida con la cantidad de CPU seleccionadas para evitar memoria innecesaria y contención de E/S:

dalvik.vm.dex2oat-cpu-set=0,1,2,3
dalvik.vm.dex2oat-threads=4

A partir de Android 12, se agregaron las siguientes opciones:

  • dalvik.vm.ps-min-first-save-ms: el tiempo de espera para que el tiempo de ejecución genere un perfil de la aplicación, la primera vez que se inicia la aplicación
  • dalvik.vm.ps-min-save-period-ms: el tiempo mínimo de espera antes de actualizar el perfil de una aplicación
  • dalvik.vm.systemservercompilerfilter: el filtro del compilador que usará el dispositivo al volver a compilar el servidor del sistema

Configuración específica A/B

configuración de la ROM

A partir de Android 7.0, los dispositivos pueden usar dos particiones del sistema para habilitar las actualizaciones del sistema A/B . Para ahorrar en el tamaño de la partición del sistema, los archivos preoptados se pueden instalar en la segunda partición del sistema no utilizada. Luego se copian en la partición de datos en el primer arranque.

Ejemplo de uso (en device-common.mk ):

PRODUCT_PACKAGES += \
     cppreopts.sh
PRODUCT_PROPERTY_OVERRIDES += \
     ro.cp_system_other_odex=1

Y en BoardConfig.mk del dispositivo:

BOARD_USES_SYSTEM_OTHER_ODEX := true

Tenga en cuenta que el código de classpath de arranque, el código del servidor del sistema y las aplicaciones principales específicas del producto siempre se compilan en la partición del sistema. De forma predeterminada, todas las demás aplicaciones se compilan en la segunda partición del sistema no utilizada. Esto se puede controlar con SYSTEM_OTHER_ODEX_FILTER , que tiene un valor predeterminado de:

SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%

Fondo dexopt OTA

Con dispositivos habilitados para A/B, las aplicaciones se pueden compilar en segundo plano para actualizarlas a la nueva imagen del sistema. Consulte Compilación de la aplicación en segundo plano para incluir opcionalmente el script de compilación y los archivos binarios en la imagen del sistema. El filtro de compilación utilizado para esta compilación se controla con:

pm.dexopt.ab-ota=speed-profile

Recomendamos usar speed-profile para aprovechar la compilación guiada por perfiles y ahorrar en almacenamiento.