理解JIT编译
目录
JIT,就是JUST IN TIME的缩写,在计算机技术体系内,JIT指一种动态编译(Dynamic Compilation) 技术。
概念
解释(Interpreter):解释就是把源程序以句为单位,每句每句的解释并执行;如果语句出现在循环体当中,比如循环10次,该语句就要被解释执行10次;解释执行过程不产生目标代码。很多脚本语言都是解释执行的。
编译(Compilation):编译是把源代码一次性翻译成目标代码,目标代码可能是可直接运行的机器码,或是已存在相应翻译器的不可执行语言。比如C/C++就是典型的编译之后才能执行的高级编程语言,这种编译也被称为静态编译(Static Compilation) 。编译有时还指将高级语言编译成一种中间形态的字节码,比如java语言,这种中间形态的字节码比如要在JVM里面才能被执行。
JIT的意思是说,首先仍然是编译compilation,但有缓存caching,不用像解释那样把循环体里面出现的代码重复解释,同时有目标机器代码。
这是相对于解释interpretation的好处。另外相对于静态编译的好处是,在编译过程对代码进行优化。选择性的编译某个函数或任意某段代码。
JIT具体的做法是这样的:当函数第一被调用时,JIT将该函数编译成机器码;当再次遇到该函数时则直接从cache中执行已编译好的机器码。
Java的JIT工作原理
JVM读入.class文件解释后,将其发给JIT编译器;JIT编译器将字节码编译成本机机器代码;
通常javac将程序源代码编译转换成java字节码,JVM通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。
很显然,解释执行速度必然会比可执行的二进制程序慢。
为了提高执行速度,引入了JIT技术,在运行时,JIT编译器将java字节码进行编译,并会把机器码保存起来,以备下次需要时使用,因此从理论上来说,采用该JIT技术可以接近以前纯编译技术。
PHP的opcache与JIT区别
首先PHP8中的JIT不是原来Opcache优化的替代,是增强。
源码(人认识)->字节码(解释器认识)->机器码(硬件认识)
来看下PHP的执行流程,假设有个x.php文件,不启用opacache的流程如下:
x.php->经过zend编译及优化->opcode->zend执行器->机器码
使用opacache的流程如下:
x.php->查找相应的opacache缓存的opcode,如果没有,则进行zend编译优化为opcode,并缓存opcode->PHP执行器->机器码
使用JIT的流程如下:
第一次:
x.php->查找相应的opacache缓存的opcode,如果没有,则进行zend编译优化为opcode,并缓存opcode->JIT编译->机器码
之后:
x.php->查找相应的opacache缓存的opcode,如果没有,则进行zend编译优化为opcode,并缓存opcode->找到相应的JIT Buffer(机器码)
- PHP8的JIT目前是在Opcache之中提供的
- JIT在Opcache优化之后的基础上,结合Runtime的信息再次优化,直接生成机器码
- JIT不是原来Opcache优化的替代,是增强
- 目前PHP8只支持x86架构的CPU
参考:
静态编译VS动态编译
静态编译优化和动态编译优化最大的不同是他们在编译时所得到的信息量的不同。
静态编译在运行程序之前就把所有的执行代码编译完,这时编译器所接受的编译信息量是不够多的。比如说:某个函数是否是大量地被调用了,函数的实参是不是一直是一个常数,等等。
动态编译之于静态编译,缺点是它需要即时编译代码,但是有一个优点:编译器可以获得静态编译期所没有的信息。比如:通过运行时的profiling可以知道哪些函数是被大量使用的。在哪些execution path上哪些函数的参数一直都没有变,等等。不要小看这些信息,当即时编译器了解这些信息之后可以在短时间内编译出比静态编译器更优质的二进制码。
举例来说,一般程序也遵循90-10原则,即运行时的90%里计算机是在处理其中10%的代码,寻找到这些执行热点代码进行深度优化能得到比静态编译更好的性能(因为已知更多信息量)。
本文收藏来自互联网,仅用于学习研究,著作权归原作者所有,如有侵权请联系删除
markdown 9ong@TsingChan
部分引用格式为收藏注解,比如本句就是注解,非作者原文。