ART中AOT和JIT编译器的区别

Posted

技术标签:

【中文标题】ART中AOT和JIT编译器的区别【英文标题】:Difference between AOT and JIT compiler in the ART 【发布时间】:2017-03-13 04:45:28 【问题描述】:

在 Marshmallow 中添加了一个带有 ART 的 AOT 编译器。从 android N 开始,除了 AOT 之外,还添加了另一个编译器 JIT。

什么是 AOT 编译器特定的作业/功能,什么是 JIT 编译器的作业/功能?

【问题讨论】:

【参考方案1】:

编译器需要两件事来生成高性能代码:信息和资源。

JIT 编译器比 AOT 编译器拥有更多的信息。静态分析在一般情况下是不可能的(您想了解的有关程序的几乎所有有趣的事情都可以简化为停机问题或莱斯定理),即使在特殊情况下也很难。 JIT 编译器没有这个问题:他们不必静态分析程序,可以在运行时动态观察。

另外,JIT 编译器拥有 AOT 编译器所没有的技术,其中最重要的一项是去优化。现在,您可能会想,我们去优化对性能很重要吗?好吧,如果您可以取消优化,那么您可能会过于激进地进行实际上无效的优化(例如内联可能是或可能不是多态的方法调用),如果事实证明您错了,您可以然后反优化回到未内联的情况(例如)。

但是,存在资源问题:AOT 编译器可以根据需要花费尽可能多的时间,并且可以使用尽可能多的内存。 JIT 编译器必须从用户现在想要使用的程序中窃取其资源。

通常,这不是问题。我们今天的机器功能如此强大,以至于 JIT 总是有足够的资源可供使用。尤其是当一次将大量新代码引入系统时,JIT 将使用最多的资源,这通常是在程序启动期间,或者程序在各个阶段之间转换时(例如,从解析配置文件到设置对象图,或者从完成配置到开始实际工作),此时程序本身通常还没有使用那么多资源(尤其是在程序启动期间)。 Azul JCA 就是一个很好的例子。它的最大配置有 864 个内核和 768 GiByte RAM(请注意,它们已经有一段时间没有出售了,所以这实际上是几年前的技术)。根据 Azul 的测量,当 JIT 非常努力工作时,它可能使用 50 个内核。这仍然是为程序、系统和 GC 剩余的 800 多个内核。

但您的典型 Android 设备没有 1000 个内核和一个 TiByte 的 RAM。而且它非常具有交互性和对延迟敏感,当用户启动 WhatsApp 时,他想立即写一条消息。不是在 500 毫秒内,当 JIT 预热时。现在。

这就是 AOT 的吸引力所在。另请注意,JIT 编译不仅会从正在运行的程序中窃取资源,它还需要电池电量,并且每次程序运行时都需要电池电量,而 AOT 编译器只需花费一次电量预算,当应用已安装。

您可以走得更远,将编译推送到应用商店甚至开发人员,就像 Apple 所做的那样,但 Apple 的优势在于要考虑的可能目标平台集要有限得多,因此在设备上AOT 编译对于 Android 来说似乎是一个合理的折衷方案。

【讨论】:

你知道的好答案,但是太长了。 很好的答案。甚至可以更长,我仍然想读它。我问自己,JIT 可用的额外信息是否真的能带来很大的性能提升。 @farhan 为什么android在构建apk的时候不直接编译.oat或者native binaries,这样安装后就不需要编译了?【参考方案2】:

在 Android 中将 Java 类转换为 DEX 字节码。 DEX 字节码格式通过 ART 或 Dalvik 运行时转换为本地机器码。

Dalvik 是一个基于 JIT(即时)编译的引擎。有 因此从 Android 4.4 (kitkat) ART 使用 Dalvik 的缺点是 作为运行时引入,它从 Android 5.0 (Lollipop) 开始 完全取代了达尔维克。 Android 7.0 增加了即时 (JIT) 带有代码分析到 Android 运行时 (ART) 的编译器 提高 Android 应用在运行时的性能。

Dalvik 使用 JIT(即时)编译,而 ART 使用 AOT(提前)编译。

准时 (JIT):

使用 Dalvik JIT 编译器,每次运行应用程序时,它都会将 Dalvik 字节码的一部分动态转换为机器码。随着执行的进行,更多的字节码被编译和缓存。由于 JIT 只编译部分代码,因此它占用的内存更小,占用的设备物理空间也更少。

提前 (AOT):

ART 配备了 Ahead-of-Time 编译器。在应用程序的安装阶段,它将 DEX 字节码静态转换为机器码并存储在设备的存储中。这是在设备上安装应用时发生的一次性事件。

Android N 包含一个混合运行时:

安装过程中不会进行任何编译,可以立即启动应用程序, 被解释的字节码。 ART 中有一个新的、更快的解释器,它伴随着一个新的 JIT,但 JIT 信息不会持久化。 相反,代码在执行期间被分析并保存结果数据。

艺术的好处:

在安装过程中完成 DEX 字节码转换后,应用程序运行速度更快。 在直接执行本机代码时减少应用程序的启动时间。 提高了电池性能,因为节省了用于逐行解释字节码的电量。 改进的垃圾收集器。

ART 的缺点:

由于在安装过程中将 DEX 字节码转换为机器码,App 安装需要更多时间。

由于安装时生成的本机机器代码存储在内部存储中,因此需要更多的内部存储。

【讨论】:

【参考方案3】:

JIT 与 AOT

.java -> .class -> .dex(by DX, D8) -> machine byte code

Just In Time(JIT) - Dalvic(基于寄存器) - 在执行前生成机器字节码。它具有更少的内存占用,但具有更大的 CPU 使用率(滞后)、周期性、电池寿命

Ahead Of Time(AOT) - Android Runtime(ART) - 在安装期间生成机器字节码。在 API 19 中引入并在 API 21 中成为默认值。 main 它具有更大的首次启动。 ART 优化内存分配和垃圾收集器 (GC) - 仅一次迭代

从 API 24 开始,ART 使用 AOT 和 JIT 的混合方法 [ClassLoader]

【讨论】:

成为 API 21 中的 default 你是说?

以上是关于ART中AOT和JIT编译器的区别的主要内容,如果未能解决你的问题,请参考以下文章

AOT 和 JIT IL2CPP和Mono CLR ILRuntime热更新原理

JVM 虚拟机 AOT 和 JIT 即时编译

JVM 虚拟机 AOT 和 JIT 即时编译

JIT和AOT编译详解

理解Java的JIT和AOT

如何使用 monotouch 编译库(出现错误:尝试使用 --aot-only 进行 JIT 编译)