1 |
|
首先编译器将我们编写好的源代码编译成IL中间语言,这些IL中间语言的主要内容是一些元数据和中间语言指令。然后再由我们的JIT编译器加载这些IL中间语言,JIT编译器会根据系统环境将IL中间语言指令转换为机器码,继而运行在不同的目标平台上,实现跨平台功能。(JIT编译器将IL中间语言即时编译成原生语言的过程和解释性语言的读取一条执行一条又有些不同,JIT会对编译结果进行缓存以便下次调取的时候直接使用)这也是为什么有些ASP.NET网站第一次运行时会较慢,而后面的执行速度则会相对快很多的一个原因。
再总结一下上面所说的编译过程:
- 首先,编译器要编历源代码,通过大量的计算生成IL中间代码,这些代码并不能直接地被CPU使用,还需要第二步操作;
- 接下来,运行时将这些IL代码通过JIT编译器进一步编译成原生的CPU指令。
在上文中我们提到了一个JIT编译器,它的全名叫即时编译器。顾名思义,它是在运行时环境中发生的编译行为。读到这里,相信很多朋友可能都会像马三一样产生疑问了。相比传统的直接将源代码编译成原生代码,C#将源代码编译成了中间语言不会降低效率嘛?原来直接一步到位的过程,现在偏要拆成两个部分。这不仅要花费更多的时间、占用更多的内存,还有可能降低性能,那用JIT编译器的好处到底有什么呢?
在我们的Unity游戏开发中就存在着AOT编译和JIT编译两种编译方式
unity公司就自行研发了IL2cpp,把本来应该再mono的虚拟机上跑的中间代码转换成cpp代码,这样再把生成的cpp代码,利用c++的跨平台特性, 在各个平台上通过对各平台都有良好优化的native c++编译器编译,以获得更高的效率和更好的兼容性。
语言在运行之前通常都需要编译,JIT(Just-in-Time,即时编译) 和 AOT(Ahead-of-Time,预编译) 则是最常见的两种编译模式。
JIT 在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。 AOT 即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。
总结来讲,在开发期使用 JIT 编译,可以缩短产品的开发周期。
那么,如何区分一门语言究竟是 AOT 还是 JIT 呢? 通常来说,看代码在执行前是否需要编译即可。如果需要编译,通常属于 AOT;如果不需要,则属于 JIT。 AOT 的典型代表是 C/C++,它们必须在执行前编译成机器码;而 JIT 的代表,则包括了如 JavaScript、Python 等几乎所有的脚本语言。