PHP8 alpha1已經(jīng)在昨天發(fā)布,相信關(guān)于JIT是大家最關(guān)心的,它到底怎么用,有什么要注意的,以及性能提升到底咋樣?
首先,我們來(lái)看一張圖:

左圖是 PHP 8之前的Opcache流程示意圖, 右圖是 PHP 8中的Opcache示意圖, 可以看出幾個(gè)關(guān)鍵點(diǎn):
PHP8的JIT是在Opcache之中提供的
目前PHP8只支持x86架構(gòu)的CPU
JIT是在原來(lái)Opcache優(yōu)化的優(yōu)化基礎(chǔ)之上進(jìn)行優(yōu)化的,不是替代
事實(shí)上JIT共用了很多原來(lái)Opcache做優(yōu)化的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),比如data flow graph, call graph, SSA等,關(guān)于這部分,后續(xù)如果有時(shí)間,可以單獨(dú)在寫(xiě)一個(gè)文章來(lái)介紹,今天就只是著重在使用層面。
下載安裝好以后,除掉原有的opcache配置以外,對(duì)于JIT我們需要添加如下配置到php.ini:
opcache.jit=1205
opcache.jit_buffer_size=64M
opcache.jit這個(gè)配置看起來(lái)稍微有點(diǎn)復(fù)雜,我來(lái)解釋下, 這個(gè)配置由4個(gè)獨(dú)立的數(shù)字組成,從左到右分別是( 請(qǐng)注意,這個(gè)是基于目前alpha1的版本設(shè)置,一些配置可能會(huì)隨著后續(xù)版本做微調(diào) ):
是否在生成機(jī)器碼點(diǎn)時(shí)候使用AVX指令, 需要CPU支持: 0: 不使用
1: 使用
寄存器分配策略: 0: 不使用寄存器分配
1: 局部(block)域分配
2: 全局(function)域分配
JIT觸發(fā)策略: 0: PHP腳本載入的時(shí)候就JIT
1: 當(dāng)函數(shù)第一次被執(zhí)行時(shí)JIT
2: 在一次運(yùn)行后,JIT調(diào)用次數(shù)最多的百分之(opcache.prof_threshold * 100)的函數(shù)
3: 當(dāng)函數(shù)/方法執(zhí)行超過(guò)N(N和opcache.jit_hot_func相關(guān))次以后JIT
4: 當(dāng)函數(shù)方法的注釋中含有@jit的時(shí)候?qū)λM(jìn)行JIT
5: 當(dāng)一個(gè)Trace執(zhí)行超過(guò)N次(和opcache.jit_hot_loop, jit_hot_return等有關(guān))以后JIT
JIT優(yōu)化策略,數(shù)值越大優(yōu)化力度越大: 0: 不JIT
1: 做opline之間的跳轉(zhuǎn)部分的JIT
2: 內(nèi)斂opcode handler調(diào)用
3: 基于類型推斷做函數(shù)級(jí)別的JIT
4: 基于類型推斷,過(guò)程調(diào)用圖做函數(shù)級(jí)別JIT
5: 基于類型推斷,過(guò)程調(diào)用圖做腳本級(jí)別的JIT
基于此,我們可以大概得到如下幾個(gè)結(jié)論:
盡量使用12x5型的配置,此時(shí)應(yīng)該是效果最優(yōu)的
對(duì)于x, 如果是腳本級(jí)別的,推薦使用0, 如果是Web服務(wù)型的,可以根據(jù)測(cè)試結(jié)果選擇3或5
@jit的形式,在有了attributes以后,可能變?yōu)?gt;
現(xiàn)在,我們來(lái)測(cè)試下啟用和不啟用JIT的時(shí)候,Zend/bench.php的差異,首先是不啟用(php -d opcache.jit_buffer_size=0 Zend/bench.php):
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
hash1(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
根據(jù)上面的介紹,我們選擇opcache.jit=1205, 因?yàn)閎ench.php是腳本(php -d opcache.jit_buffer_size=64M -d opcache.jit=1205 Zend/bench.php):
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
hash1(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
可見(jiàn), 對(duì)于Zend/bench.php, 相比不開(kāi)啟JIT,開(kāi)啟了以后,耗時(shí)降低將近60%,性能提升將近2倍 。
對(duì)于大家研究學(xué)習(xí)來(lái)說(shuō),可以通過(guò)opcache.jit_debug來(lái)觀測(cè)JIT后生成的匯編結(jié)果,比如對(duì)于:
function simple() {
$a = 0;
for ($i = 0; $i 1000000; $i++)
$a++;
}
我們通過(guò)php -d opcache.jit=1205 -dopcache.jit_debug=0x01 可以看到:
JIT$simple: ; (/tmp/1.php)
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, 我們可以得到如下結(jié)果:
JIT$simple: ; (/tmp/1.php)
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,將會(huì)有更多的信息輸出。
好了,JIT的使用就簡(jiǎn)單介紹到這里,關(guān)于JIT本身的實(shí)現(xiàn)等細(xì)節(jié),以后有時(shí)間,我再來(lái)寫(xiě)吧。
大家現(xiàn)在就可以去php.net下載PHP8來(lái)測(cè)試了 :)
thanks
到此這篇關(guān)于PHP8新特性之JIT案例講解的文章就介紹到這了,更多相關(guān)PHP8新特性之JIT內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- PHP8.0新功能之Match表達(dá)式的使用
- php curl發(fā)起get與post網(wǎng)絡(luò)請(qǐng)求案例詳解
- PHP如何刪除關(guān)聯(lián)數(shù)組中鍵值
- PHP獲取文件屬性的最簡(jiǎn)單方法
- PHP中國(guó)際化的字符串排序和比較對(duì)象詳解