JIT是在Opcache优化的基础上结合Runtime信息将字节码编译为机器码缓存起来,现有的Opcache优化不受任何影响,并且PHP的JIT是在Opcache中提供的,JIT不是对Opcache替代,而是增强,在启用JIT的情况下,如果Zend底层发现特定字节码已经编译为机器码,则可以绕过Zend VM直接让CPU执行机器码,从而提高代码性能。
opcache 配置参数参考:https://www.php.net/manual/zh/opcache.configuration.php
左图是PHP8之前的Opcache流程示意图, 右图是PHP8中的Opcache示意图
通过上图,可以看出几个关键点:
- Opcache会做opcode层面的优化,比如图中的俩条opcode合并为一条
- PHP8的JIT目前是在Opcache之中提供的
- JIT在Opcache优化之后的基础上,结合Runtime的信息再次优化,直接生成机器码
- JIT不是原来Opcache优化的替代,是增强
- 目前PHP8只支持x86架构的CPU
事实上JIT共用了很多原来Opcache做优化的基础数据结构,比如data flow graph, call graph, SSA等,关于这部分,后续如果有时间,可以单独在写一个文章来介绍,今天就只是着重在使用层面。
下载安装好以后,除掉原有的opcache配置以外,对于JIT我们需要添加如下配置到php.ini:
opcache.jit=1205
opcache.jit_buffer_size=64M
opcache.jit这个配置看起来稍微有点复杂,我来解释下, 这个配置由4个独立的数字组成,从左到右分别是(请注意,这个是基于目前alpha1的版本设置,一些配置可能会随着后续版本做微调)
1. 是否在生成机器码点时候使用AVX指令,需要CPU支持:
- 0:不使用
- 1:使用
2. 寄存器分配策略:
- 0:不使用寄存器分配
- 1:局部(block)域分配
- 2:全局(function)域分配
3. JIT触发策略:
- 0:PHP脚本载入的时候就JIT
- 1:当函数第一次被执行时JIT
- 2:在一次运行后,JIT调用次数最多的百分之(opcache.prof_threshold*100)的函数
- 3:当函数/方法执行超过N(N和opcache.jit_hot_func相关)次以后JIT
- 4:当函数方法的注释中含有 jit的时候对它进行JIT
- 5:当一个Trace执行超过N次(和opcache.jit_hot_loop,jit_hot_return等有关)以后JIT
4. JIT优化策略,数值越大优化力度越大:
- 0:不JIT
- 1:做opline之间的跳转部分的JIT
- 2:内敛opcode handler调用
- 3:基于类型推断做函数级别的JIT
- 4:基于类型推断,过程调用图做函数级别JIT
- 5:基于类型推断,过程调用图做脚本级别的JIT
基于此,我们可以大概得到如下几个结论:
- 尽量使用12×5型的配置,此时应该是效果最优的
- 对于x,如果是脚本级别的,推荐使用0,如果是Web服务型的,可以根据测试结果选择3或5
- jit的形式,在有了attributes以后,可能变为<>
PHP 8
为什么要开启这个?
源代码(人认识)->字节码(解释器认识)->机器码(硬件认识)
来看下PHP的执行流程,假设有个a.php文件,不启用opacache的流程如下:
a.php->经过zend编译->opcode->PHP解释器->机器码
启用opacache的流程如下:
a.php->查找opacache缓存,如果没有则进行zend编译为opcode并缓存->opacode->PHP解释器->机器码
启用PHP8-JIT的流程如下:
a.php->编译->机器码
以后都只执行机器码,不编译,效率上高了很多。
本文转自运维学习笔记:https://www.php.net/manual/zh/opcache.configuration.php
没有回复内容