php8引入jit后可以干什么,PHP8新特性JIT使用简介

PHP8 alpha1已经在昨天发布,相信关于JIT是大家最关心的,它到底怎么用,有什么要注意的,以及性能提升到底咋样?

首先,我们来看一张图:

488a0876e10e1ea74fb7aafb1ed337fe.png

几个关键点:

PHP8的JIT是在Opcache之中提供的

目前PHP8只支持x86架构的CPU

JIT是在原来Opcache优化的优化基础之上进行优化的,不是替代

事实上JIT共用了很多原来Opcache做优化的基础数据结构,比如data flow graph, call graph, SSA等,关于这部分后续有时间单独来写,今天就只是着重介绍使用层面。

下载安装好PHP8以后,除掉原有的opcache配置以外,对于JIT我们需要添加如下配置到php.ini:

opcache.jit=1205opcache.jit_buffer_size=64M

opcache.jit_buffer_size是定义分配多少内存给生成的机器码,这个看情况吧,一般测试就64M就行了,如果大型项目,可能要适当的大点。

opcache.jit这个配置看起来稍微有点复杂,我来解释下, 这个配置由4个独立的数字组成,从左到右分别是(请注意,这个是基于目前alpha1的版本设置,一些配置可能会随着后续版本做微调):

是否在生成机器码点时候使用AVX指令, 需要CPU支持:

0: 不使用1: 使用

寄存器分配策略:

0: 不使用寄存器分配1: 局部(block)域分配2: 全局(function)域分配

JIT触发策略:

0: PHP脚本载入的时候就JIT1: 当函数第一次被执行时JIT2: 在一次运行后,JIT调用次数最多的百分之(opcache.prof_threshold * 100)的函数3: 当函数/方法执行超过N(N和opcache.jit_hot_func相关)次以后JIT4: 当函数方法的注释中含有@jit的时候对它进行JIT5: 当一个Trace执行超过N次(和opcache.jit_hot_loop, jit_hot_return等有关)以后JIT

JIT优化策略,数值越大优化力度越大:

0: 不JIT1: 做opline之间的跳转部分的JIT2: 内敛opcode handler调用3: 基于类型推断做函数级别的JIT4: 基于类型推断,过程调用图做函数级别JIT5: 基于类型推断,过程调用图做脚本级别的JIT

基于此,我们可以大概得到如下几个结论:

尽量使用12X5型的配置,此时应该是效果最优的

对于上面的X,如果是脚本级别的,推荐使用0, 如果是Web服务型的,可以根据测试结果选择3或5

@jit的形式,在有了attributes以后,可能变为<>

现在,我们来测试下启用和不启用JIT的时候,Zend/bench.php的差异,首先是不启用(php -d opcache.jit_buffer_size=0 Zend/bench.php):

simple 0.008simplecall 0.004simpleucall 0.004simpleudcall 0.004mandel 0.035mandel2 0.055ackermann(7) 0.020ary(50000) 0.004ary2(50000) 0.003ary3(2000) 0.048fibo(30) 0.084hash1(50000) 0.013hash2(500) 0.010heapsort(20000) 0.027matrix(20) 0.026nestedloop(12) 0.023sieve(30) 0.013strcat(200000) 0.006------------------------Total 0.387

根据上面的介绍,我们选择opcache.jit=1205, 因为bench.php是脚本(php -d opcache.jit_buffer_size=64M -d opcache.jit=1205 Zend/bench.php):

simple 0.002simplecall 0.001simpleucall 0.001simpleudcall 0.001mandel 0.010mandel2 0.011ackermann(7) 0.010ary(50000) 0.003ary2(50000) 0.002ary3(2000) 0.018fibo(30) 0.031hash1(50000) 0.011hash2(500) 0.008heapsort(20000) 0.014matrix(20) 0.015nestedloop(12) 0.011sieve(30) 0.005strcat(200000) 0.004------------------------Total 0.157

可见,对于Zend/bench.php, 相比不开启JIT,开启了以后,耗时降低将近60%,性能提升将近2倍。

对于大家研究学习来说,可以通过opcache.jit_debug来观测JIT后生成的汇编结果,比如对于:

function simple(){$a = 0;for ($i = 0; $i < 1000000; $i++)$a++;}

我们通过php -d opcache.jit=1205 -dopcache.jit_debug=0x01 可以看到:

JIT$simple: ; (/tmp/1.php)sub $0x10, %rspxor %rdx, %rdxjmp .L2.L1:add $0x1, %rdx.L2:cmp $0x0, EG(vm_interrupt)jnz .L4cmp $0xf4240, %rdxjl .L1mov 0x10(%r14), %rcxtest %rcx, %rcxjz .L3mov $0x1, 0x8(%rcx).L3:mov 0x30(%r14), %raxmov %rax, EG(current_execute_data)mov 0x28(%r14), %editest $0x9e0000, %edijnz JIT$$leave_functionmov %r14, EG(vm_stack_top)mov 0x30(%r14), %r14cmp $0x0, EG(exception)mov (%r14), %r15jnz JIT$$leave_throwadd $0x20, %r15add $0x10, %rspjmp (%r15).L4:mov $0x45543818, %r15jmp JIT$$interrupt_handler

而如果我们采用opcache.jit=1201, 我们可以得到如下结果:

JIT$simple: ; (/tmp/1.php)sub $0x10, %rspcall ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLERadd $0x40, %r15jmp .L2.L1:call ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLERcmp $0x0, EG(exception)jnz JIT$$exception_handler.L2:cmp $0x0, EG(vm_interrupt)jnz JIT$$interrupt_handlercall ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLERcmp $0x0, EG(exception)jnz JIT$$exception_handlercmp $0x452a0858, %r15djnz .L1add $0x10, %rspjmp ZEND_RETURN_SPEC_CONST_LABEL

你也可以尝试各种debug的配置,比如opcache.jit_debug=0xff,将会有更多的信息输出。可以试试读读,了解JIT编译过程中间的过程。

好了,JIT的使用就简单介绍到这里,关于JIT本身的实现等细节,以后有时间,我再来写吧。

(点击阅读原文,看最新更新版) 大家现在就可以去php.net下载PHP8来测试了 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值