91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP8中的JIT是什么

發布時間:2020-06-28 16:22:35 來源:億速云 閱讀:285 作者:元一 欄目:編程語言

PHP8中的JIT是什么?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

JIT 是一種編譯器策略,它將代碼表述為一種中間狀態,在運行時將其轉換為依賴于體系結構的機器碼,并即時執行。在 PHP 中,這意味著 JIT 將為 Zend VM 生成的指令視為中間表述,并以依賴于體系結構的機器碼執行,也就是說托管代碼的不再是 Zend VM,而是更為底層的 CPU。

首先,我們來看一張圖:

PHP8中的JIT是什么

右圖有點錯誤就是,當JIT以后,下次請求的時候,會直接從JIT Buffer中讀取執行,后續我把圖改一下

左圖是PHP8之前的Opcache流程示意圖, 右圖是PHP8中的Opcache示意圖, 可以看出幾個關鍵點:

  • Opcache會做opcode層面的優化,比如圖中的倆條opcode合并為一條

  • JIT在Opcache優化之后的基礎上,再次優化,直接生成機器碼

  • PHP8的JIT是在Opcache之中提供的

  • 目前PHP8只支持x86架構的CPU

  • JIT是在原來Opcache優化的優化基礎之上進行優化的,不是替代

事實上JIT共用了很多原來Opcache做優化的基礎數據結構,比如data flow graph, call graph, SSA等,關于這部分,后續如果有時間,可以單獨在寫一個文章來介紹,今天就只是著重在使用層面。

下載安裝好以后,除掉原有的opcache配置以外,對于JIT我們需要添加如下配置到php.ini:

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>>

現在,我們來測試下啟用和不啟用JIT的時候,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
hash2(50000)       0.013
hash3(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):

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
hash2(50000)       0.011
hash3(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后生成的匯編結果,比如對于:

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, %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

大家可以嘗試閱讀這段匯編,比如其中針對i的遞增,可以看到優化力度很大,比如因為i是局部變量直接分配在寄存器中,i的范圍推斷不會大于10000,所以不需要判斷是否整數溢出等等。

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

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

這就只是簡單的內斂部分opcode handler的調用了。

你也可以嘗試各種opcache.jit的策略結合debug的配置,來觀測結果的不同,你也可以嘗試各種opcache.jit_debug的配置,比如0xff,將會有更多的輔助信息輸出。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永昌县| 夹江县| 昔阳县| 武隆县| 新平| 枣强县| 大埔县| 甘泉县| 叶城县| 林周县| 夏邑县| 沈阳市| 库尔勒市| 遵义市| 梅河口市| 尖扎县| 金塔县| 新竹县| 探索| 汉中市| 崇左市| 昭苏县| 聂拉木县| 垫江县| 建湖县| 滦平县| 瑞丽市| 靖边县| 磐安县| 温泉县| 横峰县| 虎林市| 隆子县| 岳西县| 榕江县| 浦江县| 东方市| 延边| 鄂尔多斯市| 盐源县| 天津市|