PHP8新特性之JIT案例讲解

admin3年前PHP教程29

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

首先,我们来看一张图:

左图是 PHP 8之前的Opcache流程示意图, 右图是 PHP 8中的Opcache示意图, 可以看出几个关键点:

PHP8的JIT是在Opcache之中提供的

目前PHP8只支持x86架构的CPU

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

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

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

2
3
opcache.jit=1205
 
opcache.jit_buffer_size=64M

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

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

1: 使用

寄存器分配策略: 0: 不使用寄存器分配

1: 局部(block)域分配

2: 全局(function)域分配

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

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

1: 做opline之间的跳转部分的JIT

2: 内敛opcode handler调用

3: 基于类型推断做函数级别的JIT

4: 基于类型推断,过程调用图做函数级别JIT

5: 基于类型推断,过程调用图做脚本级别的JIT

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

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

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

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

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

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
simple 0.008
 
simplecall 0.004
 
simpleucall 0.004
 
simpleudcall 0.004
 
mandel 0.035
 
mandel2 0.055
 
ackermann(7) 0.020
 
ary(50000) 0.004
 
ary2(50000) 0.003
 
ary3(2000) 0.048
 
fibo(30) 0.084
 
hasp(50000) 0.013
 
hash2(500) 0.010
 
heapsort(20000) 0.027
 
matrix(20) 0.026
 
nestedloop(12) 0.023
 
sieve(30) 0.013
 
strcat(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):

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
simple 0.002
 
simplecall 0.001
 
simpleucall 0.001
 
simpleudcall 0.001
 
mandel 0.010
 
mandel2 0.011
 
ackermann(7) 0.010
 
ary(50000) 0.003
 
ary2(50000) 0.002
 
ary3(2000) 0.018
 
fibo(30) 0.031
 
hasp(50000) 0.011
 
hash2(500) 0.008
 
heapsort(20000) 0.014
 
matrix(20) 0.015
 
nestedloop(12) 0.011
 
sieve(30) 0.005
 
strcat(200000) 0.004

------------------------

Total 0.157

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

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

2
3
4
5
6
7
8
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)

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
sub $0x10, %rsp
 
xor %rdx, %rdx
 
jmp .L2
 
.L1:
 
add $0x1, %rdx
 
.L2:
 
cmp $0x0, EG(vm_interrupt)
 
jnz .L4
 
cmp $0xf4240, %rdx
 
jl .L1
 
mov 0x10(%r14), %rcx
 
test %rcx, %rcx
 
jz .L3
 
mov $0x1, 0x8(%rcx)
 
.L3:
 
mov 0x30(%r14), %rax
 
mov %rax, EG(current_execute_data)
 
mov 0x28(%r14), %edi
 
test $0x9e0000, %edi
 
jnz JIT$$leave_function
 
mov %r14, EG(vm_stack_top)
 
mov 0x30(%r14), %r14
 
cmp $0x0, EG(exception)
 
mov (%r14), %r15
 
jnz JIT$$leave_throw
 
add $0x20, %r15
 
add $0x10, %rsp
 
jmp (%r15)
 
.L4:
 
mov $0x45543818, %r15
 
jmp JIT$$interrupt_handler

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

JIT$simple: ; (/tmp/1.php)

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
sub $0x10, %rsp
 
call ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER
 
add $0x40, %r15
 
jmp .L2
 
.L1:
 
call ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER
 
cmp $0x0, EG(exception)
 
jnz JIT$$exception_handler
 
.L2:
 
cmp $0x0, EG(vm_interrupt)
 
jnz JIT$$interrupt_handler
 
call ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER
 
cmp $0x0, EG(exception)
 
jnz JIT$$exception_handler
 
cmp $0x452a0858, %r15d
 
jnz .L1
 
add $0x10, %rsp
 
jmp ZEND_RETURN_SPEC_CONST_LABEL

你也可以尝试各种debug的配置,比如opcache.jit_debug=0xff,将会有更多的信息输出。

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

大家现在就可以去php下载PHP8来测试了 :)

thanks

到此这篇关于PHP8新特性之JIT案例讲解的文章就介绍到这了,更多相关PHP8新特性之JIT内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

免责声明:本文内容来自用户上传并发布,站点仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。请核实广告和内容真实性,谨慎使用。

相关文章

聊聊PHP中删除字符串的逗号和尾部斜杠的方法

正如标题所述,本文将给大家通过两个示例来介绍PHP删除字符串中的逗号以及尾部斜杠的方法,感兴趣的朋友咱们一起继续往下看吧~下面我们通过具体的实例分别讲解:第一个示例的要求则是“编写一个PH...

韩国站群服务器到期后信息还在吗?韩国多ip服务器租用常见问题?

相信这个问题困扰越来越多新手用户,而且在大家日常生活中,也总有韩国站群服务器到期后忘记续费,无法打开后台,无法下载网站信息等等。那么韩国站群服务器到期后信息还在吗?如果能保留,那么可以保留多长时间呢?...

韩国高防服务器抗攻击防御ddos

韩国高防服务器抗攻击防御ddos?韩国高防服务器具有出色的抗攻击防御DDoS能力。DDoS攻击是一种通过向目标服务器发送大量的请求来耗尽其网络资源和带宽的攻击方式,以达到瘫痪目标服务器的效果。韩国高防...

怎么判断江西GPU服务器哪个好

判断GPU服务器哪个好,需要考虑以下几个因素:GPU类型和数量:选择适合您工作负载需求的GPU类型和数量。例如,如果您需要进行深度学习任务,则NVIDIATeslaV100或A100GPU可能是最佳选...

GPU服务器的应用领域有哪些韩国显卡服务器的用途有

众所周知,GPU是图形处理器,在很多任务中,GPU占据着重要作用,如深度学习领域。为增进大家对GPU的了解,本文将对GPU服务器的应用领域加以介绍。GPU服务器,简单来说,GPU服务器是基于GPU的应...

php字符串中转义成特殊字符实例讲解

在php的字符串使用时,我们有学会一些转义字符,相信大家在记忆这些知识点的时候费了不少的功夫。本篇我们为大家带来的是字符串的转义方法,涉及到特殊字符的使用,主要有两种方法可以实现:mysql库函数和转...