目錄
HHVM(HipHop Virtual Machine)的起源
PHP7的效能革新
小結
首頁 後端開發 PHP7 觀賞PHP7和HHVM的性能之爭

觀賞PHP7和HHVM的性能之爭

Jun 24, 2020 pm 05:47 PM
hhvm php7


觀賞PHP7和HHVM的性能之爭

最近關於PHP7和HHVM的效能對比,成為了一個熱點的爭議話題,大家都在討論和關注哪一個才是PHP性能提升的未來。

HHVM(HipHop Virtual Machine)的起源

HHVM是一個開源的PHP虛擬機,使用JIT的編譯方式以及其他技術,讓PHP程式碼的執行效能大幅提升。據傳,可以將目前版本的原生PHP程式碼提升5-10倍的執行效能。

HHVM起源於Facebook公司,Facebook早起的許多程式碼是使用PHP來開發的,但是,隨著業務的快速發展,PHP執行效率成為越來越明顯的問題。為了優化執行效率,Facebook在2008年就開始使用HipHop,這是一種PHP執行引擎,最初是為了將Fackbook的大量PHP程式碼轉成 C ,以提高效能和節約資源。使用HipHop的PHP程式碼在效能上有數倍的提升。後來,Facebook將HipHop平台開源,逐漸發展為現在的HHVM。

 

1. PHP為什麼慢?

PHP的慢是相對於C/C 等級的語言來說,事實上,PHP語言最初的設計,就不是用來解決計算密集型的應用場景。我們可以這樣粗略理解為,PHP為了提升開發效率,而犧牲了執行效率。

我們知道PHP一個很大的特點,就是弱型別特性,也就是說,我可以隨意定義一個變量,然後給它隨意賦值為各種類型的資料。以一個int整數數字為例子,在C語言中:

int num = 200; // 通常是4位元組

但是,如果是PHP定義了一個相同的變量,實際對應的儲存結構則是:

 

這個結構體將會佔據遠比C變數多得多的內存,PHP定義方式如下:

$a = 200;//這變數將實際佔用比C變數很多倍的儲存空間。

其實對PHP來說,無論儲存什麼類型的數據,都是用上述「通殺」的結構體實現。為了相容於PHP程式設計師的變數類型“亂入”,PHP做到了對開發者的友好,但是對執行引擎很殘酷。單一變數記憶體消耗可能還不明顯,一旦用到PHP的陣列等,則複雜度指數上升(陣列的實作是HashTable)。然後,Zend引擎執行時,將這些PHP程式碼編譯為opcode(PHP的中間字節碼,格式有點類似於組譯),由Zend引擎逐行解釋執行。

無論是字串的連接操作,還是數組的簡單修改等,幾乎都是「PHP程式設計師一句話,Zend引擎跑斷腿」的節奏。因此,同樣的操作,對比C來說,PHP消耗了更多的CPU和記憶體等系統資源。除此之外,還有記憶體自動回收、變數類型判斷等等,都會增加系統資源的消耗。

例如,我用純PHP實作的快速排序函數和原生sort函數,排序10000個整數數字,來做一個耗時對比,結果如下:

## 

原生的sort耗時3.44 ms,而我們自己實作的PHP函式sort則是68.79 ms。我們發現,兩者執行效率差距龐大。我的測試方式,是計算函數執行前後的時間間隔,而不是整個PHP腳本從啟動到結束的時間。 PHP腳本啟動和關閉過程,本身有著一系列的初始化和清理工作,也會佔據不少的耗時。

 

通常情況下,PHP執行效率的排行是:

    最快的是PHP語言結構(isset、echo等),PHP語言的一部分(它們根本不是函數)。
  1. 然後比較快的就是PHP的原生和拓展函數。 PHP拓展,基於Zend API之上,用C實現的功能,執行效率和C /Java是屬於同一個數量級的。
  2. 真正慢的就是,我們透過PHP自己寫的程式碼和函數。例如,假如我們所使用的比較重的純PHP實現的框架,因為框架本身的模組很多,所以,會明顯拖累語言層面的執行效率,同時佔據更多的記憶體。 (國內的Yaf框架,以拓展的方式實現,因此執行效率遠快於純PHP寫的框架)

 

在一般情況下,我們並不建議使用過PHP實現邏輯複雜計算類型的功能,尤其是Web系統流量比較大的場景下。因此,PHP程式設計師應該對PHP的各種原生函數和各類拓展有一個比較廣泛的了解,在具體的功能實現場景中,尋求更原生的解決方案(原生接口或者拓展),而不是自己寫一堆複雜的PHP程式碼來實現這類型功能。

如果有足夠的PHP拓展開發實力,將這類型業務功能重寫為一個PHP拓展,也會大幅提升程式碼的執行效率。這是一個非常好的方式,也被廣泛應用PHP優化。但是,自己寫的PHP業務拓展的缺點也很明顯:

  1. 拓展開發耗時比較長,需求變更的時候修改也複雜,寫得不好可能會影響Web服務穩定性。 (例如,在Apache的worker模式下,多執行緒場景下掛掉,會影響同一個行程下的其他正常子執行緒。如果是多執行緒的Web模式,編寫拓展還需要支援執行緒安全性)
  2. 拓展在PHP版本升級的時候,可能需要做額外相容的工作。
  3. 人員變動後的維護和接手成本也比較高。

實際上,在網路第一線企業中,更常見的解決方案,並非增加PHP拓展,而用C/C 獨立寫一個服務server,然後PHP透過socket和服務server通訊來完成業務處理,並不將PHP本身和業務耦合在一起。

不過,Web服務大部分的效能瓶頸都在網路傳輸和其他服務server的耗時(例如MySQL等),PHP執行的耗時在整體耗時的佔用比例非常小,所以從業務角度來說,影響可能並不明顯。

 

2. HHVM提升PHP執行性能的方式

HHVM提升PHP性能的途徑,採用的方式就是取代Zend引擎來產生和執行PHP的中間字節碼(HHVM產生自己格式的中間字節碼),執行時透過JIT(Just In Time,即時編譯是種軟體最佳化技術,指在運行時才會去編譯字節碼為機器碼)轉為機器碼執行。 Zend引擎預設做法,是先編譯為opcode,然後再逐條執行,通常每個指令對應的是C語言層級的函數。如果我們產生大量重複的opcode(純PHP寫的程式碼和函數),對應的則是Zend多次逐條執行這些C程式碼。而JIT所做的則是更進一步,將大量重複執行的字節碼在運行的時候編譯為機器碼,達到提高執行效率的目的。通常,觸發JIT的條件是程式碼或函數被多次重複呼叫。

普通的PHP程式碼,因為無法固定變數的類型,需要額外加入判斷類型的邏輯程式碼,這樣PHP程式碼是不利於CPU執行和最佳化的。因此,HHVM通常需要用到Hack寫法(為了兼容某種特性而額外添加的技巧性質的代碼)的PHP代碼來“配合”,就是為了讓變量類型固定,方便虛擬機編譯執行。 PHP追求以一種形式來容納一切類型,而Hack則可以將被容納的一切標記上確定的類型。

 

PHP程式碼的Hack寫入法的範例:

##上面的例子中,PHP程式碼主要被加上了變數類型。 Hack寫法的整體方向,就是將先前「動態」的寫法變成「靜態」的寫法,來配合HHVM。

HHVM因為它的高效能而吸引了不少人的關注,一些一線網路公司也開始跟進使用。從純語言執行效能測試結果來看,HHVM領先了開發中的PHP7版本不少。

 

不過,從具體業務場景來看,HHVM和PHP7的差距並沒有那麼大,以WordPress開源部落格首頁為測試場景的結果中,他們目前的差距並不明顯。 

 

但是,PHP7目前仍在開發中,就已經可用的技術方案來看,目前的HHVM略勝一籌。不過,HHVM的部署與應用都存在一些的問題:

    服務部署較為複雜,有一定維護成本。
  1. 對PHP原生程式碼並非完整支持,PHP拓展也需要做適當的兼容。
  2. HHVM是一台新虛擬機,長時間運行有記憶體外洩。 (據說,一線網路公司在應用這個技術時,是透過自己打Patch的方式解決記憶體外洩)
 

HHVM畢竟是一個相對比較新的開源項目,發展到成熟仍然需要一定時間。

 

PHP7的效能革新

PHP長期以來飽受批評的效能問題,將會在這個版本得到大幅度的改善。版本中間沒有PHP6哈,據說,是因為這個版本曾經立過項目,後來大部分功能都在5.x的版本裡實現了,為了避免混淆,下一個大版本直接就是PHP7。 (幾年以前,我還看過關於PHP6的書。)

 

#1. PHP7的介紹

雖然PHP7的正式版本可能要到2015年的10月才發布,不過明年6月應可以看見一個測試版本了,之後是3-4個月的品質保證。

 

PHP社群的專案計畫如下:

因為專案仍然處於開發中的原因,從表格中,可以看見的特性描述都比較模糊。肯定有更多的其他特性,但尚未公佈。以下的這些,是從PHP社群看見的,因為PHP7是一個開發中的項目,以下的這些也不一定準確,不過,不妨礙我們一起來看看。

  1. PHPNG(PHP next generation,下一代PHP),對Zend執行引擎本身的各種效能最佳化,其中JIT,可能會實現在Zend Opcache元件中。
  2. AST(Abstract Syntax Tree,抽象語法樹),目的是在PHP編譯過程引入一個中間件,取代直接從解釋器吐出opcode的方式。讓解釋器和編譯器解耦,可以減少大量Hack程式碼,同時,讓實作更容易理解和維護。
  3. uniform variable syntax(統一變數語法),引入一種內部一致且完整的變數語法,讓PHP的解析器更完整地支援各種類型的變數。部分變數的用法需要調整,例如變數的變數$$a等。
  4. 支援integer semantics(整數語意),例如NaN、Infinity、<<、>>,修正list()的一致性等等。

 

在上面的特性中,最令人期待的就是PHPng的效能最佳化,PHP社群已經放出了一些效能的測速資料。從數據來看,PHPng的執行效能比起專案啟動之初,已經有接近1倍的提升。這個成績已經非常不錯,況且,最關鍵的是PHP7的優化計畫還有很多尚未完成。等到都全部完成了,相信我們可以看見一個性能更高的PHP7。

這測速資料是來自於PHP社群(wiki.php.net/phpng),而截取了一部分的資料:

 

對其目前PHP5. 6版,PHPNG的10月效能提升已經非常明顯了:

 

簡單翻譯下:

    ##綜合測試速度提升35%。
  • 在實際應用場景有20%-70%的速度提升(WordPress首頁有60%的提升)
  • #更少的記憶體消耗
  • 支援大部分常用的SAPIs
  • 支援大部分的PHP拓展綁定到資源分配(69個完成,6個待遷移)
  • 提供可堪比HHVM3.3.0的執行速度

2. PHP的弱型別爭議

PHP被爭議的特點很多,但是隨著語言版本的發布和完善,功能和特性方面的批評開始變少了。但是,PHP的「弱類型」特性,卻明顯受到更多的爭議,從HHVM透過Hack的方式直接「去掉」了「弱類型」特性可以看出,HHVM並不喜歡「弱類型」特性。然而,在我們許多PHP程式設計師的眼中,這卻是PHP的重要優點之一。 PHP裡的變因設計得隨性和飄逸,海納百川,一切皆可包容,不是讓語言顯得更為簡單嗎?

實際上,有些人認為它是個嚴重的問題,對於「弱型別」的批評觀點大致如下:

    在「嚴謹」的語言中,通常是預先定義好一個變數的類型,自始至終,變數的類型是固定的,使用範圍也是固定。而PHP的變量,通常我們只能看見它名字,類型大部分都不可以預先定義,也可以隨意改變。 (記憶體分配不好管理)
  1. 為了相容於弱型別特性,PHP需要實作大量相容程式碼,包括型別判斷、型別轉換、儲存方式等,增加了語言內部的複雜度。 (執行效率低下)
  2. 變數的類型是不可控的,在執行過程中存在大量的“隱性類型轉換”,容易產生不可預測的結果。 (這裡的確需要強調,PHP的型別轉換是個必須掌握的點,各種類型的互相轉換的可能會產生很多問題,尤其是初學PHP的同學哈)
 

#他們認為,這些都不符合「所見即所得」的簡單性,而文法嚴謹的語言更高效率,也更容易「理解」。

受到類似批評的還有Javascript等語言,因為它在這個問題上的表現是一樣的。但是,一門語言最終被大規模使用,必然有它們的道理。 PHP成為Web服務開發的首選腳本語言,Javascript則直接稱霸Web前端領域,能走到這一步都不可能是偶然因素,開發者們用腳投票選擇了它們。程式語言是人類和機器溝通的橋樑,終極追求是實現「人人皆可編程」的宏偉目標。

縱觀語言發展歷史,從0和1的機器碼開始,到組合語言,然後到C語言,再到動態腳本語言PHP。執行效率呈指數下降,但是,學習門檻也呈指數降低。 PHP語言不僅屏蔽了C的記憶體管理和指標的複雜性,而且更進一步屏蔽了變數類型的複雜性。提升了專案開發的效率,降低了學習的門檻,但同時犧牲了一定的執行效能。然後,HHVM的Hack給我們一種「回歸原始」的感覺,重新引入了變數的複雜性。當然,不同的語言解決不同場景下的問題,並不能夠一概而論。

 

小結

HHVM對PHP的效能提升,讓人眼前一亮,而磨刀霍霍的PHP7則讓人萬分期待。兩者都是極其優秀的開源項目,都在不斷前進和發展中。就目前而言,因為距離PHP7正式版的發布還有比較長的一段時間,所以目前效能優化方案的首選當然是HHVM。不過,就我個人而言,我比較看好PHP7,因為它更能做到PHP程式碼的向下相容。如果兩者性能相差不大,我會選擇簡單的。

 推薦教學:《php影片教學

以上是觀賞PHP7和HHVM的性能之爭的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

php7.0安裝了插件還是顯示未安裝怎麼辦 php7.0安裝了插件還是顯示未安裝怎麼辦 Apr 02, 2024 pm 07:39 PM

解決 PHP 7.0 中插件未顯示已安裝問題的方法:檢查插件配置並啟用插件。重新啟動 PHP 以套用配置變更。檢查插件檔案權限,確保其正確。安裝遺失的依賴項,以確保插件正常運作。如果其他步驟都失敗,則重建 PHP。其他可能原因包括外掛程式版本不相容、載入錯誤版本或 PHP 配置問題。

php7.0怎麼安裝mongo擴展 php7.0怎麼安裝mongo擴展 Nov 21, 2022 am 10:25 AM

php7.0安裝mongo擴充的方法:1、建立mongodb使用者群組和使用者;2、下載mongodb原始碼包,並將原始碼包放到“/usr/local/src/”目錄下;3、進入“src/”目錄;4、解壓縮原始碼包;5、建立mongodb檔案目錄;6、將檔案複製到「mongodb/」目錄;7、建立mongodb設定檔並修改設定即可。

php7檢測tcp埠不好用怎麼解決 php7檢測tcp埠不好用怎麼解決 Mar 22, 2023 am 09:30 AM

在php5中,我們可以使用fsockopen()函數來偵測TCP埠。這個函數可以用來開啟一個網路連接和進行一些網路通訊。但是在php7中,fsockopen()函數可能會遇到一些問題,例如無法開啟連接埠、無法連接到伺服器等。為了解決這個問題,我們可以使用socket_create()函數和socket_connect()函數來偵測TCP埠。

PHP 伺服器環境常見問題指南:快速解決常見難題 PHP 伺服器環境常見問題指南:快速解決常見難題 Apr 09, 2024 pm 01:33 PM

PHP伺服器環境常見的解決方法包括:確保已安裝正確的PHP版本和已複製相關檔案到模組目錄。暫時或永久停用SELinux。檢查並配置PHP.ini,確保已新增必要的擴充功能和進行正確設定。啟動或重新啟動PHP-FPM服務。檢查DNS設定是否有解析問題。

php7.0怎麼安裝部署 php7.0怎麼安裝部署 Nov 30, 2022 am 09:56 AM

php7.0安裝部署的方法:1、到PHP官網下載與本機系統對應的安裝版本;2、將下載的zip檔案解壓縮到指定目錄;3、開啟命令列窗口,在「E:\php7」目錄下運行“php -v”命令即可。

如何在系統重啟後自動設置unixsocket的權限? 如何在系統重啟後自動設置unixsocket的權限? Mar 31, 2025 pm 11:54 PM

如何在系統重啟後自動設置unixsocket的權限每次系統重啟後,我們都需要執行以下命令來修改unixsocket的權限:sudo...

在Docker環境中使用PECL安裝擴展時為什麼會報錯?如何解決? 在Docker環境中使用PECL安裝擴展時為什麼會報錯?如何解決? Apr 01, 2025 pm 03:06 PM

在Docker環境中使用PECL安裝擴展時報錯的原因及解決方法在使用Docker環境時,我們常常會遇到一些令人頭疼的問�...

記錄一次用strace診斷php佔用系統資源過高的問題 記錄一次用strace診斷php佔用系統資源過高的問題 May 03, 2024 pm 04:31 PM

本機環境:redhat6.7系統。 nginx1.12.1,php7.1.0,程式碼使用yii2框架問題:本地的web站需要用到elasticsearch服務。當php使用本機伺服器搭建的elasticsearch時,本地的負載都是正常。當我使用aws的elasticsearchservice服務時,本地伺服器出現負載經常過高的情況。查看nginx和php日誌,發現沒有異常。系統的並發連線數也不高。這時候想到我們老闆跟我講的一個strace診斷工具。偵錯過程:找一個php的子程序idstrace-

See all articles