ART中AOT和JIT编译器之间的区别

0xA*_*iHn 5 android jit android-6.0-marshmallow android-7.0-nougat

在棉花糖中,添加了ART的AOT编译器。从Android N起,除了AOT外,还添加了另一个编译器JIT。

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

Far*_*han 10

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

JIT compilers have way more information at their disposal than AOT compilers. Static analysis is impossible in the general case (nearly everything interesting you would want to know about a program can be reduced to either the Halting Problem or Rice's Theorem), and hard even in the special case. JIT compilers don't have this problem: they don't have to statically analyze the program, they can observe it dynamically at runtime.

Plus, a JIT compiler has techniques at its disposal that AOT compilers don't, the most important one being de-optimization. Now, you might think, we is de-optimization important for performance? Well, if you can de-optimize, then you can be over-aggressive in making optimizations that are actually invalid (like inlining a method call that may or may not be polymorphic), and if it turns out that you are wrong, you can then de-optimize back to the un-inlined case (for example).

However, there's the problem of resources: an AOT compiler can take as much time as it wants, and use as much memory as it wants. A JIT compiler has to steal its resources away from the very program that the user wants to use right now.

Normally, that is not a problem. Our today's machines are so ridiculously overpowered, that there are always enough resources at the JIT's disposal. Especially since the JIT will use the most resources when a lot of new code is introduced into the system at once, which is usually during program startup, or when the program transitions between phases (for example, from parsing the configuration files to setting up the object graph, or from finishing configuration to starting the actual work), at which times the program itself typically does not yet use that many resources (especially during program startup). The Azul JCA is a good example. It has 864 cores and 768 GiByte RAM in its biggest configuration (and note that they haven't been sold for quite some time, so that is actually several years old technology). According to Azul's measurements, the JIT uses maybe 50 cores, when it is working very hard. That's still more than 800 cores leftover for the program, the system and the GC.

But your typical Android device doesn't have 1000 cores and a TiByte of RAM. And it is extremely interactive and latency-sensitive, when the user starts, say, WhatsApp, he wants to write a message right now. Not in 500msec, when the JIT has warmed up. NOW.

That's what makes AOT attractive here. Also note that JIT compiling will not only steal resources away from the running program, it will also need battery power, and it will need that every time the program runs, whereas an AOT compiler will only need to spend that power budget once, when the app is installed.

You could go even more extreme and push the compilation off to the app store or even to the developer, like Apple does, but Apple has the advantage of a much more limited set of possible target platforms to consider, so on-device AOT compilation seems a reasonable trade-off for Android.


Mit*_*iya 7

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

Dalvik是基于JIT(及时)编译的引擎。使用Dalvik会有弊端,因此从Android 4.4(kitkat)引入了ART作为运行时,从Android 5.0(Lollipop)引入了Dalvik,从而完全取代了Dalvik。Android 7.0向Android运行时(ART)添加了具有代码概要分析功能的即时(JIT)编译器,可在运行时不断提高Android应用程序的性能。

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

及时(JIT):

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

提前(AOT):

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

Android N包含混合运行时:

安装期间不会进行任何编译,并且可以立即启动应用程序,并解释字节码。ART中有一个新的,更快的解释器,并附带了一个新的JIT,但JIT信息并未保留。而是在执行期间对代码进行概要分析,并保存结果数据。

ART的好处:

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

ART的缺点:

  • 由于安装过程中将DEX字节码转换为机器代码,因此应用程序安装需要花费更多时间。

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