Implementa el compilador justo a tiempo de ART

Android Runtime (ART) incluye un compilador justo a tiempo (JIT) con generación de perfiles de código que mejora continuamente el rendimiento de las aplicaciones para Android a medida que se ejecutan. El compilador JIT complementa el compilador anticipado (AOT) actual de ART y mejora el rendimiento del tiempo de ejecución, ahorra espacio de almacenamiento y acelera las actualizaciones del sistema y las aplicaciones. También mejora el compilador AOT, ya que evita la ralentización del sistema durante las actualizaciones automáticas de aplicaciones o la recompilación de aplicaciones durante las actualizaciones inalámbricas (OTA).

Aunque JIT y AOT usan el mismo compilador con un conjunto similar de optimizaciones, es posible que el código generado no sea idéntico. El compilador JIT utiliza información de tipo de tiempo de ejecución, puede realizar una mejor inserción de código y permite la compilación de reemplazo en la pila (OSR), todo lo cual genera un código ligeramente diferente.

Arquitectura de JIT

Arquitectura de JIT
Figura 1: Arquitectura de JIT.

Compilación JIT

La compilación JIT implica las siguientes actividades:

Compilación guiada por perfil
Figura 2: Compilación guiada por perfil.
  1. El usuario ejecuta la app, lo que hace que ART cargue el archivo .dex.
    • Si el archivo .oat (el archivo binario de AOT para el archivo .dex) está disponible, ART lo usa directamente. Si bien los archivos .oat se generan con regularidad, no siempre contienen código compilado (binario AOT).
    • Si el archivo .oat no contiene código compilado, ART ejecuta el archivo .dex a través de JIT y el intérprete.
  2. La compilación JIT está habilitada para cualquier aplicación que no se compile según el filtro de compilación speed (que indica "compila todo lo que puedas de la app").
  3. Los datos del perfil de JIT se vuelcan en un archivo de un directorio del sistema al que solo puede acceder la aplicación.
  4. El daemon de compilación AOT (dex2oat) analiza ese archivo para controlar su compilación.

    Daemon de JIT
    Figura 3: Actividades del daemon JIT.

El servicio de Google Play es un ejemplo que usan otras aplicaciones que se comportan de manera similar a las bibliotecas compartidas.

Flujo de trabajo de JIT

Arquitectura de JIT
Figura 4: Flujo de datos JIT.
  • La información de generación de perfiles se almacena en la caché de código y se somete a la recolección de elementos no utilizados bajo presión de memoria.
    • No se garantiza que una instantánea tomada cuando la aplicación estaba en segundo plano contenga datos completos (es decir, todo lo que se compiló con JIT).
    • No se intenta garantizar que se registre todo (ya que esto puede afectar el rendimiento del tiempo de ejecución).
  • Los métodos pueden tener tres estados diferentes:
    • Interpretado (código dex)
    • Compilación JIT
    • Compilado con AOT
    Si existen códigos JIT y AOT (p.ej., debido a desoptimizaciones repetidas), se prefiere el código JIT.
  • El requisito de memoria para ejecutar el JIT sin afectar el rendimiento de la app en primer plano depende de la app en cuestión. Las apps grandes requieren más memoria que las pequeñas. En general, las apps grandes se estabilizan en alrededor de 4 MB.

Cómo activar el registro de JIT

Para activar el registro de JIT, ejecuta los siguientes comandos:

adb root
adb shell stop
adb shell setprop dalvik.vm.extra-opts -verbose:jit
adb shell start

Inhabilita JIT

Para inhabilitar el JIT, ejecuta los siguientes comandos:

adb root
adb shell stop
adb shell setprop dalvik.vm.usejit false
adb shell start

Forzar la compilación

Para forzar la compilación, ejecuta el siguiente comando:

adb shell cmd package compile

Estos son algunos casos de uso comunes para forzar la compilación de un paquete específico:

  • Basadas en el perfil:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • Completa:
    adb shell cmd package compile -m speed -f my-package
    

Estos son algunos casos de uso comunes para la compilación forzada de todos los paquetes:

  • Basadas en el perfil:
    adb shell cmd package compile -m speed-profile -f -a
    
  • Completa:
    adb shell cmd package compile -m speed -f -a
    

Borrar los datos del perfil

En Android 13 o versiones anteriores

Para borrar los datos del perfil local y quitar el código compilado, ejecuta lo siguiente:

adb shell pm compile --reset 

En Android 14 o versiones posteriores

Para borrar solo los datos del perfil local, haz lo siguiente:

adb shell pm art clear-app-profiles 

Nota: A diferencia del comando para Android 13 o versiones anteriores, este comando no borra los datos del perfil externo (`.dm`) que se instalan con la app.

Para borrar los datos del perfil local y quitar el código compilado generado a partir de los datos del perfil local (es decir, para restablecer el estado de instalación), ejecuta lo siguiente:

adb shell pm compile --reset 

Nota: Este comando no quita el código compilado que se genera a partir de los datos de perfil externos (.dm) que se instalan con la app.

Para borrar todo el código compilado, ejecuta este comando:

adb shell cmd package compile -m verify -f 

Nota: Este comando conserva los datos del perfil local.