php衣食父母之3-php利用HHVM實現高效能

WBOY
發布: 2016-08-08 09:22:32
原創
1254 人瀏覽過

老闆老是想讓俺招些java程式設計師咋辦…?

他(老人家)在外面和別的陣營的工程師聊多了以後總是會來問俺,你總耍PHP(框架),

但以後咱們網站火了,負載上去了……PHP在性能上扛不住,或是安全性不如jsp(其實是java)咋辦?

俺在忙,所以就一言以斃之咯…(現在想想有點簡單粗暴的嫌疑…?)

俺(原來的)回答是: 

(您老)提出的問題就是個偽命題…因為Performance(負載)根本就不是個問題…

原因很簡單,因為我們業務是做O2O業務的,如果performance上去了(負載來了),說明一定線下的客戶也來了……

那麼(如果)俺們不是笨蛋(不特別笨的話)應該能兌現現金流了……

俺的言下之意是:如果業務做起來了,我們應該有錢了,如果有了錢,可以購買足夠的硬體設備的話,即便用PHP,也可以實現負擔高負載的在線運營……

現在仔細想想,應該再嚴謹一些……

現在就來分析一下PHP的有關性能和負載問題…(尤其是要跟java陣營的解決方案比較來看)

首先:

先看一下PHP語言(在所有計算機語言中的)的排名變化

根據“TIOBE程式語言排行榜」(榜單雖然統計方式有限制,但仍然不失為一個比較好的參考),2010年PHP最高曾經在世界程式語言中排名第三。可見,PHP語言在PC網路時代的Web領域可謂叱吒風雲,擎天一柱。 

 

在PHP程式設計師中,曾經流傳著一個段子:

某女:你能讓這個論壇的人都吵起來,我就跟你吃飯。 
PHP程式設計師:PHP是世界上最好的語言! 
某論壇炸鍋了,各種吵架…  
某女:服了你了,我們走吧! 
PHP程式設計師:今天不行,我一定要說服他們,PHP必須是最好的語言。

好了,我們言歸正傳,語言本身無分好壞,只是在各自使用的場景中解決不同的問題。網路的時代車輪是很快的,隨著行動網路的到來,在短短四年多的時間裡,行動端技術發展橫掃全球。同時,各種語言群雄並起,而昔日輝煌的PHP從原來的程式語言的榜單看,下降到第六位(2014年12月榜單)。於是,唱衰PHP的聲音此起彼落。

 

但是,鳥哥(惠新宸,PHP語言開發者之一)在2014年的Qcon分享中有一個數據,全球排名前100萬的網站中,81.3%使用的Web服務端腳本語言是PHP,2013年同期是78.3%。也就是說,PHP的在Web服務方面並沒有減少,只是在行動網路浪潮中,增加了許多其他的語言技術的應用,進而被稀釋了。

最近關於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個整數數字,來做一個耗時對比,結果如下:

 

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

 

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

  1. 最快的是PHP語言結構(isset、echo等),PHP語言的一部分(它們完全不是函數)。
  2. 接著比較快的就是PHP的原生和拓展函數。 PHP拓展,基於Zend API之上,用C實現的功能,執行效率和C++/Java是屬於同一個數量級的。
  3. 真正慢的就是,我們透過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. 服務部署較為複雜,有一定維護成本。
  2. 對PHP原生程式碼並非完整支持,PHP拓展也需要做適當的相容。
  3. 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裡的變因設計得隨性和飄逸,海納百川,一切皆可包容,不是讓語言顯得更為簡單嗎?

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

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

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

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

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

 

小結

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

參考資料:

  • https://wiki.php.net/rfc/php7timeline
  • https://wiki.php.net/phpng
  • http://hhvm.com/

以上就介紹了php衣食父母之3-php利用HHVM實現高性能,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板