全方位解讀php8.0版本優化與改進

2020-07-16 10:05:58

PHP實現了一個虛擬機器,一種虛擬處理器,我們稱之為Zend VM。PHP將人類可讀的指令碼編譯成虛擬機器能夠理解的指令(我們稱之為操作碼),這個執行階段就是我們所說的「編譯時」。在執行的「執行時」階段,虛擬機器(Zend VM)執行程式碼的指令(操作碼)。

這一切工作得很好,像APC(過去)和OPCache(現在)這樣的工具可以快取程式碼的指令(操作碼),以便「編譯時」只在必須的時候發生。

首先,有一行程式碼解釋了什麼是JIT:

Just-in-time 是一種編譯器策略,它接受程式碼的中間表示形式,並在執行時將其轉換為依賴於體系結構的機器程式碼,以便及時執行。

在PHP中,這意味著JIT將為Zend VM生成的指令作為中間表示,並行出依賴於體系結構的機器程式碼,因此程式碼的宿主不再是ZendVM,而是CPU。

為什麼PHP需要JIT?

在PHP 7.0之前,PHP內部社群關注的焦點是效能,這是由Facebook的HHVM專案帶來的良性競爭帶來的。PHP 7.0中的大部分核心更改都包含在PHPNG修補程式中,這大大改進了PHP在其核心上利用記憶體和CPU的方式,從那時起,我們每個人都被迫關注效能。

自PHP 7.0以來,已經有了一些效能改進,HashTable (PHP的核心資料結構)的優化,某些操作碼的Zend VM的專門化,某些序列的編譯器的專門化,以及對OPCache的優化器元件的不斷改進。。。除此之外還有很多其他的,太無聊了。

這是一個殘酷的事實,這些優化只能帶我們到目前為止,我們正在迅速接近,或可能已經遇到了磚牆,在我們的能力,以進一步改善它。

注意:當我們說「我們不能再改進了」時,我們真正的意思是,「我們必須做出取捨,以進一步改進它不再看起來有吸引力」。。。每當我們討論效能優化時,我們都在討論權衡。通常,在簡單性和效能之間進行權衡。我們都想認為最簡單的程式碼是最快的程式碼,但在現代的C程式設計世界中,情況並非如此。最快的程式碼通常是準備利用依賴於體系結構的內部函數或依賴於平台(編譯器)的內部函數的程式碼。簡單並不能保證最好的效能。。。

此時,PHP的JIT功能似乎是從PHP獲得更多效能的最佳方法。

JIT會讓我的網站更快嗎?

很有可能,並不明顯。

也許不是您期望的答案:在一般情況下,用PHP編寫的應用程式是I/O系結的,JITCPU系結的程式碼上工作得最好。

「I/O和CPU系結」到底是什麼意思?

當我們想要描述一段程式碼或一個應用程式的一般效能特徵時,我們使用術語I/O系結CPU系結

最簡單的說法是:

  • 如果我們能夠改進(減少、優化)它所做的I/O,那麼一段I/O系結的程式碼將會執行得更快。

  • 如果我們能夠改進(減少、優化)CPU正在執行的指令,或者(神奇地)提高CPU的時鐘速度,那麼一段CPU限制的程式碼就會執行得更快:)

  • 一段程式碼或一個應用程式可以是I/O系結、CPU系結,或者與CPU和I/O同等系結。

  • 一般來說,PHP應用程式往往是I/O系結的——減慢它們速度的是它們正在執行的I/O——連線、讀取和寫入資料庫、快取、檔案、通訊端等等。

CPU系結的PHP是什麼樣子的?

由於大多數PHP應用程式的性質,許多PHP程式設計師並不熟悉CPU系結程式碼——他們的工作往往是連線到某個資料庫,或者可能是一個快取,做一些輕量級的工作,並輸出html/json/xml響應。

您可能會環顧程式碼庫,發現許多與I/O無關的程式碼,甚至呼叫與I/O完全斷開連線的函數的程式碼,並且會感到困惑,我似乎是在暗示這並沒有使您的應用程式CPU受到限制,即使處理非I/O的程式碼行數可能比I/O多。

PHP實際上相當快,它是世界上解釋速度最快的語言之一。Zend VM呼叫與I/O無關的函數和在機器程式碼中進行相同的呼叫之間沒有顯著的區別。

這顯然是有區別的,但事實是,機器程式碼有一個呼叫約定,Zend VM有一個呼叫約定,機器程式碼有一個序言,Zend VM有一個序言:在Zend操作碼中呼叫某個c_level_function()還是機器程式碼對呼叫應用程式的效能沒有顯著影響-儘管這似乎對那個電話有很大的影響。

注意:呼叫約定大致是指在進入另一個函數之前執行的一系列指令,序言是指在進入另一個函數時執行的一系列指令:在這兩種情況下,呼叫約定都將引數推播到堆疊上,序言將它們從堆疊中彈出。

迴圈、尾呼叫和X呢?我聽說你問過:PHP實際上非常聰明,啟用了OPCache的優化器元件,你的程式碼就好像被魔法轉化成了你能編寫的最有效的形式。

現在需要注意的是,JIT不會改變Zend函數的呼叫約定,而不是VM建立的約定-Zend必須能夠在任何時候在JIT和VM模式之間切換,因此決定保留VM建立的呼叫約定。因此,當JIT執行時,隨處可見的那些呼叫並沒有明顯地加快速度。

如果您想了解CPU系結的PHP程式碼是什麼樣子的,請檢視Zend/bench.php檔案... 這顯然是一個極限的CPU程式碼範例,但它應該讓我們知道JIT真正的亮點是在數學領域。

PHP是否為加快數學速度做出了最終的權衡?

不,我們這樣做是為了擴大PHP的範圍,而且相當大。

在這個非常偏頗的PHP開發人員看來,如果你在2019年是一名web程式設計師,你還沒有考慮在下一個專案中使用PHP,那麼你做的web是錯誤的。

在PHP中提高更快地執行數學的能力,乍一看,似乎是一個非常狹窄的範圍。

然而,這實際上為機器學習、3d渲染、2d(gui)渲染和資料分析(僅舉幾個例子)開啟了大門。

為什麼我們不能在PHP 7.4中使用它呢?

我剛剛把JIT稱為「最終的權衡」,我認為它是:它可以說是有史以來最複雜的編譯器策略之一,也許是最複雜的。引入JIT就是引入相當的複雜性。

如果你問Dmitry(JIT的作者)他是否讓PHP變得複雜,他會說「不,我討厭複雜性」(這是一個直接的引語)。

歸根結底,複雜是我們所不了解的,而目前,真正了解JIT實現的內部開發人員(不到幾個)很少。

PHP 7.4的發展很快,合併到php7.4中會給我們留下一個PHP版本,只有不到幾個人可以偵錯、修復或改進(在任何實際意義上)。對於那些對合併到PHP 7.4投反對票的人來說,這種情況是不可接受的。

在從現在到PHP 8的這段時間裡,我們中的許多人將在業餘時間努力理解JIT:

我們仍然有一些要實現的特性和需要為php8重寫的工具,首先我們必須理解JIT。我們需要這一次,並非常感謝大多數選民認為適合把它交給我們。

複雜並不是可怕的同義詞:

複雜可以是美麗的,就像星雲一樣,JIT就是那種複雜。原則上,你可以完全理解某件複雜的事情,並且只在表面上的複雜程度上稍微降低一點。換句話說,即使有20個內部開發人員和Dmitry一樣熟悉JIT,它也不會真正改變JIT的複雜性。

PHP的開發速度會減慢嗎?

沒有理由認為會這樣。我們有足夠的時間可以滿懷信心地說,到PHP 8普遍可用時,我們中已經有足夠多的人熟悉JIT,至少在修復bug和推動PHP向前發展方面能夠像今天一樣發揮作用。

當試圖將這一點與JIT本質上是複雜的觀點聯絡起來時,請考慮我們花在引入新特性上的大部分時間實際上是花在討論該特性上的。對於大多數功能,甚至修復,程式碼可能需要幾分鐘或幾小時的編寫時間,而討論則需要幾週或幾個月的時間。在極少數情況下,一個特性的程式碼可能需要幾個小時或幾天的時間來編寫,但在這些極少數情況下,討論總是需要更長的時間。

PHP8 詳細解析參考《PHP8 新特性之 JIT 圖文詳解》《PHP 8 效能究竟有多大的提升?

本文由TW511.COM直譯自:https://blog.krakjoe.ninja/2019/03/php-gr8.html

以上就是全方位解讀php8.0版本優化與改進的詳細內容,更多請關注TW511.COM其它相關文章!