詳解JIT編譯器在PHP8中的工作原理
Just-In-Time
即時(shí)編譯器是PHP 8.0中最重要的新功能之一。JIT可以通過(guò)將PHP應(yīng)用程序的全部或經(jīng)常調(diào)用的部分作為CPU機(jī)器代碼編譯并存儲(chǔ)并直接執(zhí)行,從而繞過(guò)Zend VM及其過(guò)程開(kāi)銷(xiāo),從而提高性能。
但它也增加了調(diào)試的障礙,因?yàn)閼?yīng)用程序的某些部分可能作為CPU機(jī)器代碼緩存,而標(biāo)準(zhǔn)PHP調(diào)試器無(wú)法使用。PHP 8.0的JIT pull-request
在PHP代碼庫(kù)中增加了50,000多個(gè)新行,因此,除了從事JIT的開(kāi)發(fā)人員之外,PHP核心開(kāi)發(fā)人員本身可能并不精通。
JIT是傳統(tǒng)解釋器和AOT編譯器的混合體。混合模型帶來(lái)了這兩種方法的利弊,而經(jīng)過(guò)微調(diào)的應(yīng)用程序可以勝過(guò)JIT的弊端。
大多數(shù)PHP應(yīng)用程序都接受HTTP請(qǐng)求,從數(shù)據(jù)庫(kù)中檢索和處理數(shù)據(jù),并返回結(jié)果。IO通常是重要的性能瓶頸:從磁盤(pán)讀取數(shù)據(jù),寫(xiě)入和網(wǎng)絡(luò)請(qǐng)求。
什么是 JIT?
JIT 是 Just-In-Time 編譯的縮寫(xiě),是一種在運(yùn)行時(shí)將高級(jí)源代碼編譯成機(jī)器碼的技術(shù)。傳統(tǒng)的 PHP 解釋器將 PHP 源代碼逐行解釋執(zhí)行,而 JIT 編譯器將 PHP 源代碼在運(yùn)行時(shí)編譯成機(jī)器碼,然后執(zhí)行編譯后的機(jī)器碼,從而提高了執(zhí)行效率。
JIT 在 PHP 8 中的引入
在 PHP 8 中,JIT 編譯器是一個(gè)全新的 Zend 引擎特性。這個(gè)功能的目標(biāo)是通過(guò)編譯和緩存熱代碼路徑來(lái)提高 PHP 腳本的性能。PHP 8 的 JIT 編譯器可以顯著加快 PHP 應(yīng)用程序的執(zhí)行速度,特別是對(duì)于 CPU 密集型的任務(wù)。
JIT 編譯器的工作原理
JIT 編譯器的核心思想是將 PHP 源代碼分為熱代碼路徑和冷代碼路徑。熱代碼路徑是那些在運(yùn)行時(shí)頻繁執(zhí)行的代碼塊,而冷代碼路徑是相對(duì)不常執(zhí)行的代碼塊。
以下是 JIT 編譯器在 PHP 8 中的工作原理:
- 熱代碼路徑識(shí)別:
在 PHP 腳本的執(zhí)行過(guò)程中,Zend 引擎會(huì)跟蹤哪些代碼塊被頻繁執(zhí)行。這些熱代碼路徑會(huì)被標(biāo)記以備編譯。 - 代碼分析和優(yōu)化:
熱代碼路徑中的 PHP 源代碼將被 JIT 編譯器分析和優(yōu)化。這個(gè)過(guò)程包括對(duì)代碼進(jìn)行類(lèi)型推斷和更好的代碼生成。 - 機(jī)器碼生成:
一旦代碼經(jīng)過(guò)分析和優(yōu)化,JIT 編譯器將生成相應(yīng)的機(jī)器碼。 - 機(jī)器碼緩存:
生成的機(jī)器碼被緩存以備將來(lái)使用,這樣在下次執(zhí)行相同的代碼路徑時(shí),無(wú)需再次編譯。 - 執(zhí)行機(jī)器碼:
一旦機(jī)器碼被緩存,PHP 腳本的執(zhí)行將切換到執(zhí)行機(jī)器碼而不是解釋 PHP 源代碼,從而實(shí)現(xiàn)性能提升。
JIT 在 PHP 8 中的配置
在 PHP 8 中,你可以通過(guò)配置來(lái)啟用或禁用 JIT 編譯器以及調(diào)整其行為。以下是一些與 JIT 相關(guān)的配置選項(xiàng):
opcache.jit
:這是 JIT 編譯器的主要配置選項(xiàng)。你可以設(shè)置為"tracing"
(默認(rèn)值)以啟用 JIT 編譯器,或設(shè)置為"off"
以禁用 JIT 編譯器。opcache.jit_buffer_size
:用于配置 JIT 編譯緩沖區(qū)的大小。opcache.jit_debug
:用于啟用或禁用 JIT 編譯器的調(diào)試模式,以幫助診斷性能問(wèn)題。
示例:?jiǎn)⒂?JIT 編譯器
以下是一個(gè)示例代碼,演示如何在 PHP 8 中啟用 JIT 編譯器以加速 PHP 腳本的執(zhí)行。創(chuàng)建一個(gè) PHP 腳本,例如 jit_example.php
,并添加以下內(nèi)容:
<?php ini_set('opcache.jit', 'tracing'); function fibonacci($n) { if ($n <= 1) { return $n; } else { return fibonacci($n - 1) + fibonacci($n - 2); } } $start = microtime(true); $result = fibonacci(35); $end = microtime(true); $elapsed = $end - $start; echo "Fibonacci result: $result\n"; echo "Elapsed time: $elapsed seconds\n";
在這個(gè)示例中,我們啟用了 JIT 編譯器,然后定義了一個(gè)遞歸的 Fibonacci 函數(shù)來(lái)測(cè)試性能。運(yùn)行這個(gè)腳本并觀察輸出,你將看到 JIT 編譯器在編譯和執(zhí)行代碼時(shí)的影響。
Function JIT相比之下,F(xiàn)unction JIT模式是一個(gè)相當(dāng)簡(jiǎn)單的模式。它通過(guò)JIT編譯整個(gè)函數(shù),而無(wú)需跟蹤常用的代碼結(jié)構(gòu),例如函數(shù)內(nèi)部的循環(huán)。它仍然支持對(duì)常用函數(shù)進(jìn)行性能分析,并在執(zhí)行應(yīng)用程序請(qǐng)求之前,之后或期間觸發(fā)JIT編譯或編譯后的機(jī)器代碼的執(zhí)行。
Tracing JITTracing JIT(在PHP 8.0中默認(rèn)選擇)試圖識(shí)別經(jīng)常使用的代碼部分,并選擇性地編譯這些結(jié)構(gòu),以在編譯時(shí)間和內(nèi)存使用之間取得最佳平衡。并非所有的編程語(yǔ)言都支持tracing JIT編譯器,但是PHP支持從第一個(gè)發(fā)行版開(kāi)始就支持tracing JIT,并且默認(rèn)情況下也是選中的。
有幾個(gè)配置選項(xiàng)可以進(jìn)一步調(diào)整如何確定熱代碼結(jié)構(gòu),例如函數(shù)調(diào)用的次數(shù),循環(huán)結(jié)構(gòu)的迭代次數(shù)等。
分析和優(yōu)化JIT可以在代碼運(yùn)行時(shí)對(duì)其進(jìn)行檢查,分析和優(yōu)化。PHP JIT提供了對(duì)閾值和觸發(fā)器的細(xì)粒度控制,其中涉及多少調(diào)用使其成為將JIT編譯為機(jī)器代碼的合適候選者,并且可以使用新編譯的代碼。如果在緩沖區(qū)中也存在后續(xù)的請(qǐng)求,則可以使用編譯后的代碼。
JIT友好代碼當(dāng)JIT可以盡可能多地分流到本機(jī)CPU寄存器和指令時(shí),它將受益匪淺。PHP是一種弱類(lèi)型的語(yǔ)言,這使得很難推斷變量的類(lèi)型,并且需要對(duì)變量的生命周期進(jìn)行更多分析,因?yàn)樽兞康念?lèi)型可能在同一代碼結(jié)構(gòu)的稍后位置發(fā)生變化。
嚴(yán)格類(lèi)型的代碼以及具有標(biāo)量類(lèi)型的函數(shù)可以幫助JIT推斷類(lèi)型,并在可能的情況下利用CPU寄存器和專(zhuān)用指令。例如,一個(gè)純函數(shù)(沒(méi)有副作用),啟用嚴(yán)格類(lèi)型并帶有參數(shù)和返回類(lèi)型可能是理想的選擇:
declare(strict_types=1); function?sum(float?$a,?float?$b):?float?{ ????return?$a?+?$b; }
當(dāng)PHP無(wú)法推斷類(lèi)型時(shí),它可能無(wú)法充分利用JIT優(yōu)化。
實(shí)際上,PHP 7的一些改進(jìn)來(lái)自這些優(yōu)化,它們可以消除無(wú)效代碼并改善引用計(jì)數(shù)。這意味著更嚴(yán)格類(lèi)型化的代碼為PHP提供了更多機(jī)會(huì)來(lái)優(yōu)化Opcache級(jí)別和JIT級(jí)別的代碼。
基本的JIT配置默認(rèn)情況下,JIT是啟用的,但可通過(guò)限制緩沖區(qū)大小將其關(guān)閉。
最簡(jiǎn)單的設(shè)置是簡(jiǎn)單地為JIT設(shè)置緩沖區(qū)大小,然后JIT將使用合理的默認(rèn)值。
opcache.enable=1 opcache.enable_cli=1 opcache.jit_buffer_size=256M
到此這篇關(guān)于詳解JIT編譯器在PHP8中的工作原理的文章就介紹到這了,更多相關(guān)JIT在PHP8中工作原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
php使用cookie保存用戶(hù)登錄的用戶(hù)名實(shí)例
這篇文章主要介紹了php使用cookie保存用戶(hù)登錄的用戶(hù)名實(shí)現(xiàn)方法,實(shí)例形式完整分析了cookie保存用戶(hù)登錄名的技巧,需要的朋友可以參考下2015-01-01php調(diào)用mysql存儲(chǔ)過(guò)程實(shí)例分析
這篇文章主要介紹了php調(diào)用mysql存儲(chǔ)過(guò)程,綜合各種常見(jiàn)實(shí)例分析了php調(diào)用mysql存儲(chǔ)過(guò)程的各種常見(jiàn)操作與使用技巧,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12php獲取post中的json數(shù)據(jù)的實(shí)現(xiàn)方法
最近用到ext與PHP交互,ext把json數(shù)據(jù)post給PHP,但在PHP里面$_post獲取不到,$_REQUEST也獲取不到,但是通過(guò)firedebug看到的請(qǐng)求信息確實(shí)是把JSON數(shù)據(jù)post給了PHP,這什么情況2011-06-06php實(shí)現(xiàn)在新浪云中使用imagick生成縮略圖并上傳的方法
這篇文章主要介紹了php實(shí)現(xiàn)在新浪云中使用imagick生成縮略圖并上傳的方法,涉及新浪云SaeStorage類(lèi)的相關(guān)操作技巧,需要的朋友可以參考下2016-09-09PHP讀取txt文件的內(nèi)容并賦值給數(shù)組的代碼
使用file_get_contents()獲取txt文件的內(nèi)容,然后通過(guò)explode()把獲得的字符串轉(zhuǎn)化為數(shù)組。獲得數(shù)組長(zhǎng)度可以使用count()函數(shù)2011-11-11php面向?qū)ο笾衧tatic靜態(tài)屬性與方法的內(nèi)存位置分析
這篇文章主要介紹了php面向?qū)ο笾衧tatic靜態(tài)屬性與方法的內(nèi)存位置,通過(guò)內(nèi)存位置實(shí)例分析了static靜態(tài)屬性的原理與使用技巧,需要的朋友可以參考下2015-02-02php使用strpos判斷字符串中數(shù)字類(lèi)型子字符串出錯(cuò)的解決方法
這篇文章主要介紹了php使用strpos判斷字符串中數(shù)字類(lèi)型子字符串出錯(cuò)的解決方法,結(jié)合具體問(wèn)題分析了strpos函數(shù)針對(duì)數(shù)字類(lèi)型子字符串進(jìn)行判斷時(shí)的注意事項(xiàng)及類(lèi)型轉(zhuǎn)換處理技巧,需要的朋友可以參考下2017-04-04PHP獲取一年中每個(gè)星期的開(kāi)始和結(jié)束日期的方法
這篇文章主要介紹了PHP獲取一年中每個(gè)星期的開(kāi)始和結(jié)束日期的方法,涉及php對(duì)日期操作的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02