实施 ART 即时 (JIT) 编译器

Android 运行时 (ART) 包括一个即时 (JIT) 编译器,该编译器具有代码分析功能,可在 Android 应用程序运行时不断提高它们的性能。 JIT 编译器补充了 ART 当前的提前 (AOT) 编译器,提高了运行时性能,节省了存储空间,并加速了应用程序和系统更新。它还通过避免在自动应用程序更新期间系统减速或在无线 (OTA) 更新期间重新编译应用程序来改进 AOT 编译器。

尽管 JIT 和 AOT 使用具有相似优化集的相同编译器,但生成的代码可能并不相同。 JIT 利用运行时类型信息,可以进行更好的内联,并使堆栈替换 (OSR) 编译成为可能,所有这些都会生成略有不同的代码。

即时架构

即时架构
图 1. JIT 架构。

即时编译

JIT 编译涉及以下活动:

配置文件引导的comp
图 2.配置文件引导的编译。
  1. 用户运行应用程序,然后触发 ART 加载.dex文件。
    • 如果.oat文件( .dex文件的 AOT 二进制文件)可用,ART 会直接使用它。尽管.oat文件会定期生成,但它们并不总是包含已编译的代码(AOT 二进制文件)。
    • 如果.oat文件不包含编译后的代码,ART 会通过 JIT 和解释器运行来执行.dex文件。
  2. 对于任何未根据speed编译过滤器编译的应用程序(即“尽可能从应用程序编译”)启用 JIT。
  3. JIT 配置文件数据被转储到系统目录中只有应用程序可以访问的文件中。
  4. AOT 编译 ( dex2oat ) 守护程序解析该文件以驱动其编译。

    JIT 守护进程
    图 3. JIT 守护程序活动。

Google Play 服务是其他应用程序使用的示例,其行为类似于共享库。

JIT 工作流程

即时架构
图 4. JIT 数据流。
  • 分析信息存储在代码缓存中,并在内存压力下进行垃圾回收。
    • 不能保证当应用程序在后台时拍摄的快照将包含完整的数据(即,所有被 JIT 处理的数据)。
    • 没有尝试确保记录所有内容(因为这会影响运行时性能)。
  • 方法可以处于三种不同的状态:
    • 解释(dex 代码)
    • 即时编译
    • AOT 编译
    如果同时存在 JIT 和 AOT 代码(例如由于重复的反优化),则首选 JIT 代码。
  • 在不影响前台应用程序性能的情况下运行 JIT 所需的内存取决于相关应用程序。大型应用程序比小型应用程序需要更多内存。通常,大型应用程序稳定在 4 MB 左右。

打开 JIT 日志记录

要打开 JIT 日志记录,请运行以下命令:

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

禁用 JIT

要禁用 JIT,请运行以下命令:

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

强制编译

要强制编译,请运行以下命令:

adb shell cmd package compile

强制编译特定包的常见用例:

  • 基于配置文件:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • 完整:
    adb shell cmd package compile -m speed -f my-package
    

强制编译所有包的常见用例:

  • 基于配置文件:
    adb shell cmd package compile -m speed-profile -f -a
    
  • 完整:
    adb shell cmd package compile -m speed -f -a
    

清除配置文件数据

要清除配置文件数据并删除已编译的代码,请运行以下命令:

  • 对于一个包:
    adb shell cmd package compile --reset my-package
    
  • 对于所有包:
    adb shell cmd package compile --reset -a