JIT[Just-In-Time],也就是即时编译,边运行边编译[动态编译]。AOT[Ahead-Of-Time],指运行前编译,是两种程序的编译方式。比较这两种编译方式之前,先比较编译器[Compiler]和解释器[Interpreter]。

Compiler vs Interpreter

首先,我们平时使用的编程语言,计算机是不理解的。为了能够运行在机器上运行,必须把编写好的程序[program]转化为计算机可以理解的机器代码[machine code],这个过程就是编译。编译器和解释器的关键区别在于是否编译和执行过程是否是同时进行。如果向C语言一样,先要编译,再运行,这就是使用Compiler,如果向python一样,编译和运行并没有明显的界限,那就是Interpreter。

Compiler Interpreter
Compiler scans the entire program and translates the whole of it into machine code at once. Interpreter translates just one statement of the program at a time into machine code.
A compiler takes a lot of time to analyze the source code. However, the overall time taken to execute the process is much faster. An interpreter takes very less time to analyze the source code. However, the overall time to execute the process is much slower.
A compiler always generates an intermediary object code. It will need further linking. Hence more memory is needed. An interpreter does not generate an intermediary code. Hence, an interpreter is highly efficient in terms of its memory.
A compiler generates the error message only after it scans the complete program and hence debugging is relatively harder while working with a compiler. Keeps translating the program continuously till the first error is confronted. If any error is spotted, it stops working and hence debugging becomes easy.
Compliers are used by programming languages like C and C++ for example. Interpreters are used by programming languages like Ruby and Python for example.

Why JIT

以Java,C#,NET为代表的语言是建立在虚拟机之上的,虚拟机可以提供更好的跨平台移植性,但是为了做到这一点,这些语言都有中间代码[Java里就是bytecode],中间代码处于程序和机器代码中间,独立与任何操作系统,只能被虚拟机[比如JVM]自己理解。所以,只要拥有你程序的中间代码和对应的虚拟机,你的程序可以在任何机器上运行。

此时,一个编译过程就被分成了两部分,程序编译成中间代码,中间代码转换成机器代码。问题就出现在这个转换,默认情况下,虚拟机传统的解释器[注意这里是解释器,比如Java Interpreter],就是要在中间语言,和真正的平台体系结构之间的指令做映射。比如把Java的load指令换成native code的load指令。但是根据上面的表格,我们看出,解释起有一个问题就是translates just one statement of the program at a time into machine code,那要是一个for loop,这转化成机器代码的过程就太慢了[执行时间随着循环次数而累加]。

JIT的出现[比如Java JIT],就是是为了弥补虚拟机边运行边解释的低性能,它会智能地对热点代码进行优化且重复利用。从策略的角度来讲,就是通过查表或者缓存而不是重复解决子问题而大大缩短解决问题的时间。这里的热点代码,主要就是只两个,被多次调用的方法被多次调用的循环体

所以现在能够理解JIT为什么叫Just-In-Time了,就是在解释代码的过程中发现有一段程序需要编译那就just in time,赶紧编译一下,并且把它放到缓存中以便下次使用。现在JIT的概念已经被泛化,泛指再程序解释或者运行过程中,可以通过预先编译部分代码为机器码来提高执行速度的策略

从另一个角度看,JIT算是集合了Compiler和Interpreter的优点的混合体。

JIT vs AOT

JIT的优点

  1. 可以根据当前程序的运行情况生成最优的机器指令序列

  2. 可以根据进程中内存的实际情况调整代码使内存能够更充分的利用。

  3. 初次编译后,频繁使用的代码会被预先编译为机器码并存在缓存中,之后的程序运行速度会有提升。

JIT的缺点

  1. 编译需要占用运行时资源会导致进程卡顿

  2. 编译优化不完全的情况下,编译时间会变长,因为JIT的时间是包含在运行之间中,也会无形中延长运行时间。

  3. 在编译准备和识别频繁使用的方法需要占用时间,使得初始编译会需要更长的时间,也就是说,比不使用JIT方式的初次编译需要更长时间

AOT的优点

  1. 在程序运行前编译,可以避免在运行时的编译性能消耗和内存消耗

  2. 编译之后,程序初次运行也不存在冷启动问题

AOT的缺点

  1. 大型程序的编译时间,本省就很长,每次运行之前都要进行编译,非常耗时

  2. 保存编译好的程序会占用更多内存。