Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Mejoras de Android 8.0 ART

El tiempo de ejecución de Android (ART) se ha mejorado significativamente en la versión de Android 8.0. La siguiente lista resume las mejoras que los fabricantes de dispositivos pueden esperar en ART.

Recolector de basura de compactación concurrente

Como se anunció en Google I / O, ART presenta un nuevo recolector de basura (GC) de compactación simultánea en Android 8.0. Este recopilador compacta el montón cada vez que se ejecuta GC y mientras se ejecuta la aplicación, con solo una breve pausa para procesar las raíces del hilo. Estos son sus beneficios:

  • GC siempre compacta el montón: tamaños de montón un 32% más pequeños en promedio en comparación con Android 7.0.
  • La compactación permite la asignación de objetos de puntero de golpe local de subproceso: las asignaciones son un 70% más rápidas que en Android 7.0.
  • Ofrece tiempos de pausa un 85% más pequeños para la prueba H2 en comparación con Android 7.0 GC.
  • Los tiempos de pausa ya no se escalan con el tamaño del montón; las aplicaciones deberían poder utilizar grandes cantidades sin preocuparse por el jank.
  • Detalle de implementación de GC - Leer barreras:
    • Las barreras de lectura son una pequeña cantidad de trabajo realizado para cada campo de objeto leído.
    • Están optimizados en el compilador, pero pueden ralentizar algunos casos de uso.

Optimizaciones de bucle

ART emplea una amplia variedad de optimizaciones de bucle en la versión de Android 8.0:

  • Eliminaciones de cheques de límites
    • Estático: se ha demostrado que los rangos están dentro de los límites en tiempo de compilación
    • Dinámico: las pruebas en tiempo de ejecución aseguran que los bucles permanezcan dentro de los límites (desactive de lo contrario)
  • Eliminaciones de variables de inducción
    • Eliminar la inducción muerta
    • Reemplazar la inducción que se usa solo después del ciclo por expresiones de forma cerrada
  • Eliminación de códigos muertos dentro del cuerpo del bucle, eliminación de bucles completos que se vuelven muertos
  • Reducción de fuerza
  • Transformaciones de bucle: reversión, intercambio, división, desenrollado, unimodular, etc.
  • SIMDización (también llamada vectorización)

El optimizador de bucle reside en su propio paso de optimización en el compilador ART. La mayoría de las optimizaciones de bucle son similares a las optimizaciones y simplificaciones en otros lugares. Los desafíos surgen con algunas optimizaciones que reescriben el CFG de una manera más elaborada de lo habitual, porque la mayoría de las utilidades de CFG (ver nodes.h) se enfocan en construir un CFG, no en reescribir uno.

Análisis de jerarquía de clases

ART en Android 8.0 usa Class Hierarchy Analysis (CHA), una optimización del compilador que desvirtualiza las llamadas virtuales en llamadas directas según la información generada al analizar las jerarquías de clases. Las llamadas virtuales son caras ya que se implementan en torno a una búsqueda de vtable y requieren un par de cargas dependientes. Además, las llamadas virtuales no se pueden insertar.

A continuación, se muestra un resumen de las mejoras relacionadas:

  • Actualización dinámica del estado del método de implementación única: al final del tiempo de vinculación de la clase, cuando se ha llenado vtable, ART realiza una comparación entrada por entrada con la vtable de la superclase.
  • Optimización del compilador: el compilador aprovechará la información de implementación única de un método. Si un método A.foo tiene una bandera de implementación única establecida, el compilador desvirtualizará la llamada virtual en una llamada directa y, como resultado, intentará incorporar la llamada directa.
  • Invalidación de código compilado: también al final del tiempo de vinculación de la clase cuando se actualiza la información de implementación única, si el método A.foo que anteriormente tenía implementación única pero ese estado ahora está invalidado, todo el código compilado que depende de la suposición de que el método A. foo tiene necesidades de implementación única para invalidar su código compilado.
  • Desoptimización: para el código compilado en vivo que está en la pila, se iniciará la desoptimización para forzar el código compilado invalidado al modo de intérprete para garantizar la corrección. Se utilizará un nuevo mecanismo de desoptimización que es un híbrido de desoptimización sincrónica y asincrónica.

Cachés en línea en archivos .oat

ART ahora emplea cachés en línea y optimiza los sitios de llamadas para los que existen suficientes datos. La función de cachés en línea registra información adicional en tiempo de ejecución en perfiles y la usa para agregar optimizaciones dinámicas a la compilación anticipada.

Dexlayout

Dexlayout es una biblioteca introducida en Android 8.0 para analizar archivos dex y reordenarlos según un perfil. Dexlayout tiene como objetivo utilizar la información de creación de perfiles en tiempo de ejecución para reordenar secciones del archivo dex durante la compilación de mantenimiento inactivo en el dispositivo. Al agrupar partes del archivo dex a las que a menudo se accede juntas, los programas pueden tener mejores patrones de acceso a la memoria desde una localidad mejorada, ahorrando RAM y acortando el tiempo de inicio.

Dado que la información del perfil está disponible actualmente solo después de que se hayan ejecutado las aplicaciones, dexlayout se integra en la compilación en el dispositivo de dex2oat durante el mantenimiento inactivo.

Eliminación de caché dex

Hasta Android 7.0, el objeto DexCache poseía cuatro matrices grandes, proporcionales a la cantidad de ciertos elementos en DexFile, a saber:

  • cadenas (una referencia por DexFile :: StringId),
  • tipos (una referencia por DexFile :: TypeId),
  • métodos (un puntero nativo por DexFile :: MethodId),
  • campos (un puntero nativo por DexFile :: FieldId).

Estas matrices se utilizaron para la recuperación rápida de objetos que resolvimos previamente. En Android 8.0, se han eliminado todas las matrices excepto la matriz de métodos.

Rendimiento del intérprete

El rendimiento del intérprete mejoró significativamente en la versión de Android 7.0 con la introducción de "mterpillar", un intérprete que presenta un mecanismo central de búsqueda / decodificación / interpretación escrito en lenguaje ensamblador. Mterpillar sigue el modelo del rápido intérprete de Dalvik y admite arm, arm64, x86, x86_64, mips y mips64. Para el código computacional, el método de Art es aproximadamente comparable al intérprete rápido de Dalvik. Sin embargo, en algunas situaciones puede ser significativamente, e incluso dramáticamente, más lento:

  1. Invocar desempeño.
  2. Manipulación de cadenas y otros usuarios habituales de métodos reconocidos como intrínsecos en Dalvik.
  3. Mayor uso de memoria de pila.

Android 8.0 soluciona estos problemas.

Más inlining

Desde Android 6.0, ART puede incorporar cualquier llamada dentro de los mismos archivos dex, pero solo puede incorporar métodos de hoja de diferentes archivos dex. Había dos razones para esta limitación:

  1. Inlinar desde otro archivo dex requiere usar la caché dex de ese otro archivo dex, a diferencia de la misma inserción de archivo dex, que podría simplemente reutilizar la caché dex de la persona que llama. La caché dex es necesaria en el código compilado para un par de instrucciones como llamadas estáticas, carga de cadenas o carga de clases.
  2. Los mapas de pila solo codifican un índice de método dentro del archivo dex actual.

Para abordar estas limitaciones, Android 8.0:

  1. Elimina el acceso a la caché dex del código compilado (consulte también la sección "Eliminación de la caché de Dex")
  2. Extiende la codificación del mapa de pila.

Mejoras de sincronización

El equipo de ART ajustó las rutas de código MonitorEnter / MonitorSalir y redujo nuestra dependencia de las barreras de memoria tradicionales en ARMv8, reemplazándolas con instrucciones más nuevas (adquirir / liberar) cuando fue posible.

Métodos nativos más rápidos

Las llamadas nativas más @FastNative a la interfaz nativa de Java (JNI) están disponibles mediante las anotaciones @FastNative y @CriticalNative . Estas optimizaciones de tiempo de ejecución ART incorporadas aceleran las transiciones JNI y reemplazan la notación JNI! Bang ahora obsoleta. Las anotaciones no tienen ningún efecto en los métodos no nativos y solo están disponibles para el código de lenguaje Java de la plataforma en la bootclasspath la bootclasspath (sin actualizaciones de Play Store).

La anotación @FastNative admite métodos no estáticos. Use esto si un método accede a un jobject como parámetro o valor de retorno.

La anotación @CriticalNative proporciona una forma aún más rápida de ejecutar métodos nativos, con las siguientes restricciones:

  • Los métodos deben ser estáticos, sin objetos para parámetros, valores devueltos o un this implícito.
  • Solo los tipos primitivos se pasan al método nativo.
  • El método nativo no usa los parámetros JNIEnv y jclass en su definición de función.
  • El método debe registrarse con RegisterNatives lugar de depender de la vinculación dinámica de JNI.

@FastNative puede mejorar el rendimiento del método nativo hasta 3 veces y @CriticalNative hasta 5 veces. Por ejemplo, una transición JNI medida en un dispositivo Nexus 6P:

Invocación de Java Native Interface (JNI) Tiempo de ejecución (en nanosegundos)
JNI regular 115
! bang JNI 60
@FastNative 35
@CriticalNative 25