溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP7和HHVM的性能對(duì)比

發(fā)布時(shí)間:2020-06-28 10:29:37 來(lái)源:億速云 閱讀:259 作者:Leah 欄目:編程語(yǔ)言

今天就跟大家聊聊有關(guān)PHP7和HHVM的性能對(duì)比,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

HHVM(HipHop Virtual Machine)的起源

HHVM是一個(gè)開(kāi)源的PHP虛擬機(jī),使用JIT的編譯方式以及其他技術(shù),讓PHP代碼的執(zhí)行性能大幅提升。據(jù)傳,可以將當(dāng)前版本的原生PHP代碼提升5-10倍的執(zhí)行性能。

HHVM起源于Facebook公司,F(xiàn)acebook早起的很多代碼是使用PHP來(lái)開(kāi)發(fā)的,但是,隨著業(yè)務(wù)的快速發(fā)展,PHP執(zhí)行效率成為越來(lái)越明顯的問(wèn)題。為了優(yōu)化執(zhí)行效率,F(xiàn)acebook在2008年就開(kāi)始使用HipHop,這是一種PHP執(zhí)行引擎,最初是為了將Fackbook的大量PHP代碼轉(zhuǎn)成 C++,以提高性能和節(jié)約資源。使用HipHop的PHP代碼在性能上有數(shù)倍的提升。后來(lái),F(xiàn)acebook將HipHop平臺(tái)開(kāi)源,逐漸發(fā)展為現(xiàn)在的HHVM。

1. PHP為什么慢?

PHP的慢是相對(duì)于C/C++級(jí)別的語(yǔ)言來(lái)說(shuō),事實(shí)上,PHP語(yǔ)言最初的設(shè)計(jì),就不是用來(lái)解決計(jì)算密集型的應(yīng)用場(chǎng)景。我們可以這樣粗略理解為,PHP為了提升開(kāi)發(fā)效率,而犧牲了執(zhí)行效率。

我們知道PHP一個(gè)很大的特點(diǎn),就是弱類(lèi)型特性,也就是說(shuō),我可以隨意定義一個(gè)變量,然后給它隨意賦值為各種類(lèi)型的數(shù)據(jù)。以一個(gè)int整型數(shù)字為例子,在C語(yǔ)言中:

int num = 200; // 通常是4字節(jié)

但是,如果是PHP定義了一個(gè)同樣的變量,實(shí)際對(duì)應(yīng)的存儲(chǔ)結(jié)構(gòu)則是:

PHP7和HHVM的性能對(duì)比

這個(gè)結(jié)構(gòu)體將會(huì)占據(jù)遠(yuǎn)比C變量多得多的內(nèi)存,PHP中定義方式如下:

$a = 200;//這變量將實(shí)際占用對(duì)比C變量很多倍的存儲(chǔ)空間。

其實(shí)對(duì)PHP來(lái)說(shuō),無(wú)論存儲(chǔ)什么類(lèi)型的數(shù)據(jù),都是用上述“通殺”的結(jié)構(gòu)體實(shí)現(xiàn)。為了兼容PHP程序員的變量類(lèi)型“亂入”,PHP做到了對(duì)開(kāi)發(fā)者的友好,但是對(duì)執(zhí)行引擎很殘酷。單個(gè)變量?jī)?nèi)存消耗可能還不明顯,一旦用到PHP的數(shù)組等,則復(fù)雜度指數(shù)上升(數(shù)組的實(shí)現(xiàn)是HashTable)。然后,Zend引擎執(zhí)行時(shí),將這些PHP代碼編譯為opcode(PHP的中間字節(jié)碼,格式有點(diǎn)類(lèi)似于匯編),由Zend引擎逐行解釋執(zhí)行。

無(wú)論是字符串的連接操作,還是數(shù)組的簡(jiǎn)單修改等,幾乎都是“PHP程序員一句話,Zend引擎跑斷腿”的節(jié)奏。因此,同樣的操作,對(duì)比C來(lái)說(shuō),PHP消耗了更多的CPU和內(nèi)存等系統(tǒng)資源。除此之外,還有內(nèi)存自動(dòng)回收、變量類(lèi)型判斷等等,都會(huì)增加系統(tǒng)資源的消耗。

原生的sort耗時(shí)3.44 ms,而我們自己實(shí)現(xiàn)的PHP函數(shù)sort則是68.79 ms。我們發(fā)現(xiàn),兩者執(zhí)行效率差距巨大。我的測(cè)試方式,是計(jì)算函數(shù)執(zhí)行前后的時(shí)間間隔,而不是整個(gè)PHP腳本從啟動(dòng)到結(jié)束的時(shí)間。PHP腳本啟動(dòng)和關(guān)閉過(guò)程,本身有著一系列的初始化和清理工作,也會(huì)占據(jù)不少的耗時(shí)。

PHP7和HHVM的性能對(duì)比

通常情況下,PHP執(zhí)行效率的排行是:

  1. 最快的是PHP語(yǔ)言結(jié)構(gòu)(isset、echo等),PHP語(yǔ)言的一部分(它們根本不是函數(shù))。
  2. 然后比較快的就是PHP的原生和拓展函數(shù)。PHP拓展,基于Zend API之上,用C實(shí)現(xiàn)的功能,執(zhí)行效率和C++/Java是屬于同一個(gè)數(shù)量級(jí)的。
  3. 真正慢的就是,我們通過(guò)PHP自己寫(xiě)的代碼和函數(shù)。例如,假如我們使用的比較重的純PHP實(shí)現(xiàn)的框架,因?yàn)榭蚣鼙旧淼哪K很多,所以,會(huì)明顯拖累語(yǔ)言層面的執(zhí)行效率,同時(shí)占據(jù)更多的內(nèi)存。(國(guó)內(nèi)的Yaf框架,以拓展的方式實(shí)現(xiàn),因此執(zhí)行效率遠(yuǎn)快于純PHP寫(xiě)的框架)

PHP7和HHVM的性能對(duì)比

在一般情況下,我們并不推薦用過(guò)PHP實(shí)現(xiàn)邏輯復(fù)雜計(jì)算類(lèi)型的功能,尤其是Web系統(tǒng)流量比較大的場(chǎng)景下。因此,PHP程序員應(yīng)該對(duì)PHP的各種原生函數(shù)和各類(lèi)拓展有一個(gè)比較廣泛的了解,在具體的功能實(shí)現(xiàn)場(chǎng)景中,尋求更原生的解決方案(原生接口或者拓展),而不是自己寫(xiě)一堆復(fù)雜的PHP代碼來(lái)實(shí)現(xiàn)這類(lèi)型功能。

如果有足夠的PHP拓展開(kāi)發(fā)實(shí)力,將這類(lèi)型業(yè)務(wù)功能重寫(xiě)為一個(gè)PHP拓展,也會(huì)大幅提升代碼的執(zhí)行效率。這是一個(gè)非常不錯(cuò)的方式,也被廣泛應(yīng)用PHP優(yōu)化中。但是,自己編寫(xiě)的PHP業(yè)務(wù)拓展的缺點(diǎn)也很明顯:

  1. 拓展開(kāi)發(fā)耗時(shí)比較長(zhǎng),需求變更的時(shí)候修改也復(fù)雜,寫(xiě)得不好可能會(huì)影響Web服務(wù)穩(wěn)定性。(例如,在Apache的worker模式下,多線程場(chǎng)景下掛掉,會(huì)影響同一個(gè)進(jìn)程下的其他正常子線程。如果是多線程的Web模式,編寫(xiě)拓展還需要支持線程安全)
  2. 拓展在PHP版本升級(jí)的時(shí)候,可能需要做額外的兼容工作。
  3. 人員變動(dòng)后的維護(hù)和接手成本也比較高。

實(shí)際上,在互聯(lián)網(wǎng)一線企業(yè)中,更常見(jiàn)的解決方案,并非增加PHP拓展,而用C/C++獨(dú)立寫(xiě)一個(gè)服務(wù)server,然后PHP通過(guò)socket和服務(wù)server通信來(lái)完成業(yè)務(wù)處理,并不將PHP本身和業(yè)務(wù)耦合在一起。

不過(guò),Web服務(wù)大部分的性能瓶頸都在網(wǎng)絡(luò)傳輸和其他服務(wù)server的耗時(shí)上(例如MySQL等),PHP執(zhí)行的耗時(shí)在整體耗時(shí)的占用比例非常小,所以從業(yè)務(wù)角度來(lái)說(shuō),影響可能并不明顯。

2. HHVM提升PHP執(zhí)行性能的方式

HHVM提升PHP性能的途徑,采用的方式就是替代Zend引擎來(lái)生成和執(zhí)行PHP的中間字節(jié)碼(HHVM生成自己格式的中間字節(jié)碼),執(zhí)行時(shí)通過(guò)JIT(Just In Time,即時(shí)編譯是種軟件優(yōu)化技術(shù),指在運(yùn)行時(shí)才會(huì)去編譯字節(jié)碼為機(jī)器碼)轉(zhuǎn)為機(jī)器碼執(zhí)行。Zend引擎默認(rèn)做法,是先編譯為opcode,然后再逐條執(zhí)行,通常每條指令對(duì)應(yīng)的是C語(yǔ)言級(jí)別的函數(shù)。如果我們產(chǎn)生大量重復(fù)的opcode(純PHP寫(xiě)的代碼和函數(shù)),對(duì)應(yīng)的則是Zend多次逐條執(zhí)行這些C代碼。而JIT所做的則是更進(jìn)一步,將大量重復(fù)執(zhí)行的字節(jié)碼在運(yùn)行的時(shí)候編譯為機(jī)器碼,達(dá)到提高執(zhí)行效率的目的。通常,觸發(fā)JIT的條件是代碼或者函數(shù)被多次重復(fù)調(diào)用。

PHP7和HHVM的性能對(duì)比

普通的PHP代碼,因?yàn)闊o(wú)法固定變量的類(lèi)型,需要額外添加判斷類(lèi)型的邏輯代碼,這樣PHP代碼是不利于CPU執(zhí)行和優(yōu)化的。因此,HHVM通常需要用到Hack寫(xiě)法(為了兼容某種特性而額外添加的技巧性質(zhì)的代碼)的PHP代碼來(lái)“配合”,就是為了讓變量類(lèi)型固定,方便虛擬機(jī)編譯執(zhí)行。PHP追求以一種形式來(lái)容納一切類(lèi)型,而Hack則可以將被容納的一切標(biāo)記上確定的類(lèi)型。

PHP代碼的Hack寫(xiě)法的例子:

PHP7和HHVM的性能對(duì)比

上面的例子中,PHP代碼主要被添加上了變量類(lèi)型。Hack寫(xiě)法的總體方向,就是將之前“動(dòng)態(tài)”的寫(xiě)法變?yōu)椤办o態(tài)”的寫(xiě)法,來(lái)配合HHVM。

HHVM因?yàn)樗母咝阅芏瞬簧偃说年P(guān)注,一些一線互聯(lián)網(wǎng)公司也開(kāi)始跟進(jìn)使用。從純語(yǔ)言執(zhí)行性能測(cè)試結(jié)果來(lái)看,HHVM領(lǐng)先了開(kāi)發(fā)中的PHP7版本不少。

PHP7和HHVM的性能對(duì)比

不過(guò),從具體業(yè)務(wù)場(chǎng)景來(lái)看,HHVM和PHP7的差距并沒(méi)有那么大,以WordPress開(kāi)源博客首頁(yè)為測(cè)試場(chǎng)景的結(jié)果中,他們目前的差距并不明顯。

PHP7和HHVM的性能對(duì)比

但是,PHP7目前還在開(kāi)發(fā)中,就已經(jīng)可用的技術(shù)方案來(lái)看,目前的HHVM略勝一籌。不過(guò),HHVM的部署和應(yīng)用都存在一些的問(wèn)題:

  1. 服務(wù)部署比較復(fù)雜,有一定維護(hù)成本。
  2. 對(duì)PHP原生代碼并非完整支持,PHP拓展也需要做適當(dāng)?shù)募嫒荨?/li>
  3. HHVM是個(gè)新虛擬機(jī),長(zhǎng)時(shí)間運(yùn)行有內(nèi)存泄露。(據(jù)說(shuō),一線互聯(lián)網(wǎng)公司在應(yīng)用這個(gè)技術(shù)時(shí),是通過(guò)自己打Patch的方式解決內(nèi)存泄露)

HHVM畢竟是一個(gè)相對(duì)比較新的開(kāi)源項(xiàng)目,發(fā)展到成熟仍然需要一定時(shí)間。

PHP7的性能革新

PHP長(zhǎng)期以來(lái)飽受批評(píng)的性能問(wèn)題,將會(huì)在這個(gè)版本得到大幅度的改善。版本中間沒(méi)有PHP6哈,據(jù)說(shuō),是因?yàn)檫@個(gè)版本曾經(jīng)立過(guò)項(xiàng)目,后來(lái)大部分功能都在5.x的版本里實(shí)現(xiàn)了,為了避免混淆,下一個(gè)大版本直接就是PHP7。(幾年以前,我還看到過(guò)關(guān)于PHP6的書(shū)籍。)

1. PHP7的介紹

雖然PHP7的正式版本可能要到2015年的10月份才發(fā)布,不過(guò)明年6月份應(yīng)可以看見(jiàn)一個(gè)測(cè)試版本了,之后是3-4個(gè)月的質(zhì)量保證。

PHP社區(qū)的項(xiàng)目計(jì)劃如下:

PHP7和HHVM的性能對(duì)比

因?yàn)轫?xiàng)目仍然處于開(kāi)發(fā)中的原因,從表格中,可以看見(jiàn)的特性描述都比較模糊??隙ㄓ懈嗟钠渌匦裕皇巧形垂?。下面的這些,是從PHP社區(qū)看見(jiàn)的,因?yàn)镻HP7是一個(gè)開(kāi)發(fā)中的項(xiàng)目,下面的這些也不一定準(zhǔn)確,不過(guò),不妨礙我們一起來(lái)看看。

  1. PHPNG(PHP next generation,下一代PHP),對(duì)Zend執(zhí)行引擎本身的各種性能優(yōu)化,其中JIT,可能會(huì)實(shí)現(xiàn)在Zend Opcache組件中。
  2. AST(Abstract Syntax Tree,抽象語(yǔ)法樹(shù)),目的是在PHP編譯過(guò)程引入一個(gè)中間件,替代直接從解釋器吐出opcode的方式。讓解釋器和編譯器解耦,可以減少大量Hack代碼,同時(shí),讓實(shí)現(xiàn)更容易理解和維護(hù)。
  3. uniform variable syntax(統(tǒng)一變量語(yǔ)法),引入一種內(nèi)部一致和完整的變量語(yǔ)法,讓PHP的解析器更完整地支持各種類(lèi)型的變量。部分變量的用法需要調(diào)整,例如變量的變量$$a等。
  4. 支持integer semantics(整型語(yǔ)義),例如NaN、Infinity、<<、>>,修正list()的一致性等等。

上面的特性中,最令人期待的就是PHPng的性能優(yōu)化,PHP社區(qū)已經(jīng)放出了一些性能的測(cè)速數(shù)據(jù)。從數(shù)據(jù)上看,PHPng的執(zhí)行性能比起項(xiàng)目啟動(dòng)之初,已經(jīng)有接近1倍的提升。這個(gè)成績(jī)已經(jīng)非常不錯(cuò),況且,最關(guān)鍵的是PHP7的優(yōu)化計(jì)劃還有很多尚未完成。等到都全部完成了,相信我們可以看見(jiàn)一個(gè)性能更高的PHP7。

這測(cè)速數(shù)據(jù)是來(lái)自于PHP社區(qū)(wiki.php.net/phpng),截取了一部分的數(shù)據(jù):

PHP7和HHVM的性能對(duì)比

對(duì)其當(dāng)前PHP5.6版本,PHPNG的10月份性能提升已經(jīng)非常明顯了:

PHP7和HHVM的性能對(duì)比

簡(jiǎn)單翻譯下:

  • 綜合測(cè)試速度提升35%。
  • 在實(shí)際應(yīng)用場(chǎng)景有20%-70%的速度提升(WordPress首頁(yè)有60%的提升)
  • 更少的內(nèi)存消耗
  • 支持大部分常用的SAPIs
  • 支持大部分的PHP拓展綁定到資源分配(69個(gè)完成,6個(gè)待遷移)
  • 提供堪比HHVM3.3.0的執(zhí)行速度

2. PHP的弱類(lèi)型爭(zhēng)議

PHP被爭(zhēng)議的特點(diǎn)很多,但是隨著語(yǔ)言版本的發(fā)布和完善,功能和特性方面的批評(píng)開(kāi)始變少了。但是,PHP的“弱類(lèi)型”特性,卻明顯受到更多的爭(zhēng)議,從HHVM通過(guò)Hack的方式直接“去掉”了“弱類(lèi)型”特性可以看出,HHVM并不喜歡“弱類(lèi)型”特性。然而,在我們很多PHP程序員的眼中,這卻是PHP的重要優(yōu)點(diǎn)之一。PHP里的變量被設(shè)計(jì)得隨性和飄逸,海納百川,一切皆可包容,不是讓語(yǔ)言顯得更為簡(jiǎn)單嗎?

實(shí)際上,有些人認(rèn)為它是個(gè)嚴(yán)重的問(wèn)題,對(duì)于“弱類(lèi)型”的批評(píng)觀點(diǎn)大致如下:

  1. 在“嚴(yán)謹(jǐn)”的語(yǔ)言中,通常是預(yù)先定義好一個(gè)變量的類(lèi)型,自始至終,變量的類(lèi)型是固定的,使用范圍也是固定。而PHP的變量,通常我們只能看見(jiàn)它名字,類(lèi)型大部分都不可以預(yù)先定義,并且還可以隨意改變。(內(nèi)存分配不好管理)
  2. 為了兼容弱類(lèi)型特性,PHP需要實(shí)現(xiàn)大量兼容代碼,包括類(lèi)型判斷、類(lèi)型轉(zhuǎn)換、存儲(chǔ)方式等,增加了語(yǔ)言內(nèi)部的復(fù)雜度。(執(zhí)行效率低下)
  3. 變量的類(lèi)型是不可控的,在執(zhí)行過(guò)程中存在大量的“隱性類(lèi)型轉(zhuǎn)換”,容易產(chǎn)生不可預(yù)知的結(jié)果。(這里的確需要強(qiáng)調(diào),PHP的類(lèi)型轉(zhuǎn)換是個(gè)必須掌握的點(diǎn),各種類(lèi)型的互相轉(zhuǎn)換的可能會(huì)產(chǎn)生很多問(wèn)題,尤其是初學(xué)PHP的同學(xué)哈)

他們認(rèn)為,這些都不符合“所見(jiàn)即所得”的簡(jiǎn)單性,而語(yǔ)法嚴(yán)謹(jǐn)?shù)恼Z(yǔ)言更高效率,也更容易“理解”。

受到類(lèi)似批評(píng)的還有Javascript等語(yǔ)言,因?yàn)樗谶@個(gè)問(wèn)題上的表現(xiàn)是一樣的。但是,一門(mén)語(yǔ)言最終被大規(guī)模使用,必然有它們的道理。PHP成為Web服務(wù)開(kāi)發(fā)的首選腳本語(yǔ)言,Javascript則直接稱(chēng)霸Web前端領(lǐng)域,能走到這一步都不可能是偶然因素,開(kāi)發(fā)者們用腳投票選擇了它們。編程語(yǔ)言是人類(lèi)和機(jī)器溝通的橋梁,終極追求是實(shí)現(xiàn)“人人皆可編程”的宏偉目標(biāo)。

縱觀語(yǔ)言發(fā)展歷史,從0和1的機(jī)器碼開(kāi)始,到匯編語(yǔ)言,然后到C語(yǔ)言,再到動(dòng)態(tài)腳本語(yǔ)言PHP。執(zhí)行效率呈指數(shù)下降,但是,學(xué)習(xí)門(mén)檻也呈指數(shù)降低。PHP語(yǔ)言不僅屏蔽了C的內(nèi)存管理和指針的復(fù)雜性,而且更進(jìn)一步屏蔽了變量類(lèi)型的復(fù)雜性。提升了項(xiàng)目開(kāi)發(fā)的效率,降低了學(xué)習(xí)的門(mén)檻,但同時(shí)犧牲了一定的執(zhí)行性能。然后,HHVM的Hack給我們一種“回歸原始”的感覺(jué),重新引入了變量的復(fù)雜性。當(dāng)然,不同的語(yǔ)言解決不同場(chǎng)景下的問(wèn)題,并不能夠一概而論。

看完上述內(nèi)容,你們對(duì)PHP7和HHVM的性能對(duì)比有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI