首頁 >後端開發 >php教程 >HHVM 是如何提升 PHP 效能的?

HHVM 是如何提升 PHP 效能的?

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB原創
2016-07-27 16:56:201143瀏覽
Andrei Alexandrescu on AMA

背景

HHVM 是Facebook 開發的高性能PHP 虛擬機,宣稱比官方的快9倍,我很好奇,於是抽空簡單了解了一下,並整理出這篇文章,希望能回答清楚兩方面的問題:

  • HHVM 到底靠譜麼?是否可以用到產品中?
  • 為什麼它比官方的 PHP 快很多?到底是如何優化的?

你會怎麼做?

在討論HHVM 實現原理之前,我們先設身處地想想:假設你有個PHP 寫的網站遇到了性能問題,經分析後發現很大一部分資源就耗在PHP 上,這時你會怎麼優化PHP性能?

例如可以有以下幾種方式:

  • 方案1,遷移到效能較好的語言上,如 Java、C++、Go。
  • 方案2,透過 RPC 將功能分離出來用其它語言實現,讓 PHP 做更少的事情,比如 Twitter 就將大量業務邏輯放到了 Scala 中,前端的 Rails 只負責展現。
  • 方案3,寫 PHP 擴展,在效能瓶頸地方換 C/C++。
  • 方案4,最佳化 PHP 的效能。

方案1幾乎不可行,十年前Joel 就拿Netscape 的例子警告過, 你將放棄是多年的經驗積累,尤其是像Facebook 這種業務邏輯複雜的產品,PHP 代碼實在太多了,據稱有2千萬行(引用自[PHP on the Metal with HHVM]),修改起來的成本恐怕比寫個虛擬機還大,而且對於一個上千人的團隊,從頭開始學習也是不可接受的。

方案2是最保險的方案,可以逐步遷移,事實上Facebook 也在朝這方面努力了,而且還開發了Thrift 這樣的RPC 解決方案,Facebook 內部主要使用的另一個語言是C++,從早期的Thrift 程式碼就能看出來,因為其它語言的實作都很簡陋,沒辦法在生產環境下使用。

目前在Facebook 中據稱PHP:C++ 已經從9:1 增加到7:3 了,加上有Andrei Alexandrescu 的存在,C++ 在Facebook 中越來越流行,但這只能解決部分問題,畢竟C++開發成本比PHP 高很多,不適合用在經常修改的地方,太多RPC 的呼叫也會嚴重影響效能。

方案3看起來美好,實際執行起來卻很難,一般來說性能瓶頸並不會很顯著,大多是不斷累加的結果,加上PHP 擴展開發成本高,這種方案一般只用在公共且變化不大的基礎庫上,所以這種方案解決不了多少問題。

可以看到,前面3個方案並不能很好地解決問題,所以 Facebook 其實沒有選擇的餘地,只能去考慮 PHP 本身的最佳化了。

更快的 PHP

既然要最佳化 PHP,那要如何去最佳化呢?在我看來可以有以下幾種方法:

  • 方案1,PHP 語言層面的最佳化。
  • 方案2,最佳化 PHP 的官方實作(也就是 Zend)。
  • 方案3,將 PHP 編譯成其它語言的 bytecode(字節碼),借助其它語言的虛擬機器(如 JVM)來運作。
  • 方案4,將 PHP 轉換成 C/C++,然後編譯成本地程式碼。
  • 方案5,開發更快的 PHP 虛擬機器。

PHP 語言層面的最佳化是最簡單可行的,Facebook 當然想到了,而且還開發了 XHProf 這樣的效能分析工具,對於定位效能瓶頸是很有幫助的。

不過XHProf 還是沒能很好解決Facebook 的問題,所以我們繼續看,接下來是方案2,簡單來看,Zend 的執行過程可以分成兩部分:將PHP 編譯成opcode、執行opcode,所以優化Zend 可以從這兩方面來考慮。

最佳化opcode 是一種常見的做法,可以避免重複解析PHP,而且還能做一些靜態的編譯最佳化,例如Zend Optimizer Plus,但由於PHP 語言的動態性,這種最佳化方法是有限制的,樂觀估計也只能提升20%的性能。另一個考量是優化 opcode 架構本身,例如基於暫存器的方式,但這種做法修改起來工作量太大,效能提升也不會特別明顯(可能30%?),所以投入產出比不高。

另一個方法是最佳化opcode 的執行,首先簡單提一下Zend 是如何執行的,Zend 的interpreter(也叫解釋器)在讀到opcode 後,會根據不同的opcode 呼叫不同函數(其實有些是switch,不過為了描述方便我簡化了),然後在這個函數中執行各種語言相關的操作(感興趣的話可看看深入理解PHP 內核這本書),所以Zend 中並沒有什麼複雜封裝和間接調用,作為一個解釋器來說已經做得很好了。

想要提升Zend 的執行效能,就需要對程式的底層執行有所解,例如函數呼叫其實是有開銷的,所以能透過Inline threading 來優化掉,它的原理就像C 語言中的inline關鍵字那樣,但它是在運行時將相關的函數展開,然後依次執行(只是打個比方,實際實現不太一樣),同時也避免了CPU 流水線預測失敗導致的浪費。

另外還可以像 JavaScriptCore 和 LuaJIT 那樣使用彙編來實作 interpreter,具體細節建議看看 Mike 的解釋

但這兩種做法修改代價太大,甚至比重寫一個還難,尤其是要保證向下兼容,後面提到 PHP 的特點時你就知道了。

開發一個高效能的虛擬機器不是件簡單的事情,JVM 花了10多年才達到現在的效能,那是否能直接利用這些高效能的虛擬機器來最佳化 PHP 的效能呢?這就是方案3的思路。

其實這種方案早就有人嘗試過了,像是 Quercus 和 IBM 的 P8,Quercus 幾乎沒見有人使用,而 P8 也已經死掉了。 Facebook 也曾經研究過這種方式,甚至還出現過不靠譜的傳聞 ,但其實 Facebook 在2011年就放棄了。

因為方案3看起來美好,但實際效果卻不理想,按照很多大牛的說法(比如Mike),VM 總是為某個語言優化的,其它語言在上面實現會遇到很多瓶頸,比如動態的方法調用,關於這點在Dart 的文檔中有過介紹,而且據說Quercus 的性能與Zend+APC 比差不了太多([來自The HipHop Compiler for PHP]),所以沒太大意義。

不過 OpenJDK 這幾年也在努力,最近的 Grall 專案看起來還不錯,也有語言在上面取得了顯著的效果,但我還沒空研究 Grall,所以這裡無法判斷。

接下來是方案4,它正是HPHPc(HHVM 的前身)的做法,原理是將PHP 程式碼轉成C++,然後編譯為本地文件,可以認為是一種AOT(ahead of time)的方式,關於其中程式碼轉換的技術細節可以參考The HipHop Compiler for PHP 這篇論文,以下是該論文中的一個截圖,可以透過它來大概了解:

HHVM 是如何提升 PHP 性能的?

這種做法的最大優點是實現簡單(相對於一個VM 來說),而且能做很多編譯優化(因為是離線的,慢點也沒事),比如上面的例子就將- 1優化掉了,但它很難支援PHP 中的許多動態的方法,如eval()create_function(),因為這就得再內嵌一個interpreter,成本不小,所以HPHPc 乾脆就直接不支援這些語法。

除了HPHPc,還有兩個類似的項目,一個是Roadsend,另一個是phc ,phc 的做法是將PHP 轉成了C 再編譯,以下是它將file_get_contents($f) 轉成C 程式碼的例子:

<div class="blockcode"> <div id="code_LjU"><ol> <li>static php_fcall_info fgc_info;</li> <li>php_fcall_info_init ("file_get_contents", &fgc_info);</li> <li>php_m.75; 🎜>php_call_function (&fgc_info);</li> <li> </ol></div>複製程式碼<em onclick="copycode($('code_LjU'));"></em> <p>話說phc 作者曾經在博客上哭訴,說他兩年前就去Facebook 演示過phc 了,還和那裡的工程師交流過,結果人家一發布就火了,而自己忙活了4年卻默默無聞,現在前途渺茫。 。 。 </p> <p>Roadsend 也已經不維護了,對於PHP 這樣的動態語言來說,這種做法有很多的局限性,由於無法動態include,Facebook 將所有文件都編譯到了一起,上線時的文件部署居然達到了1G,越來越不可接受了。 </p> <p>另外有還有一個叫 PHP QB 的項目,由於時間關係我沒看,感覺可能是類似的東東。 </p> <p>所以就只剩下一條路了,那就是寫一個更快的PHP 虛擬機,將一條黑路走到底,或許你和我一樣,一開始聽到Facebook 要做一個虛擬機是覺得太離譜,但仔細分析就會發現其實也只有這樣了。 </p> <h2>更快的虛擬機器</h2> <p>HHVM 為什麼比較快?在各種新聞報導中都提到了JIT 這個關鍵技術,但其實遠沒有那麼簡單,JIT 不是什麼神奇的魔法棒,用它輕輕一揮就能提升性能,而且JIT 這個操作本身也是會耗時的,對於簡單的程式沒準還比interpreter 慢,最極端的例子是LuaJIT 2 的Interpreter 就稍微比V8 的JIT 快,所以並不存在絕對的事情,更多還是在細節問題的處理上,HHVM 的發展歷史就是不斷優化的歷史,你可以從下圖看到它是如何一點點超過HPHPc 的:</p> <img alt="HHVM 是如何提升 PHP 性能的?" src="http://img.it-home.org/data/attachment/forum/2014pic/20140321154123_97.jpg" style="max-width:90%" style="max-width:90%"> <p>值得一提的是在Android 4.4 中新的虛擬機器ART 就採用的是AOT 方案(還記得麼?前面提到的HPHPc 就是這種),結果比之前使用JIT 的Dalvik 快了一倍,所以說JIT 不一定比AOT 快。 </p> <p>因此這個專案是有很大風險的,如果沒有強大的內心和毅力,極有可能半途而廢,Google 就曾經想用JIT 提升Python 的性能,但最終失敗了,對於Google 來說用到Python 的地方其實沒什麼性能問題(好吧,以前Google 是用Python 寫過crawl [參考In The Plex],但那都是1996年的事情了)。 </p> <p>比起 Google,Facebook 顯然有更大的動力和決心,PHP 是 Facebook 最重要的語言,我們來看看 Facebook 都投入了哪些大牛到這個項目中(不全): </p> <ul> <li>Andrei Alexandrescu,『Modern C++ Design』和『C++ Coding Standards』的作者,C++ 領域無可爭議的大神</li> <li>Keith Adams,負責過 VMware 核心架構,當年 VMware 就派他一人去和 Intel 進行技術合作,足以證明在 VMM 領域他有多了解了</li> <li>Drew Paroski,在微軟參與過 .NET 虛擬機器開發,改進了其中的 JIT</li> <li>Jason Evans,開發了 jemalloc,減少了 Firefox 一半的記憶體消耗</li> <li>Sara Golemon,『Extending and Embedding PHP』的作者,PHP 核心專家,這本書估計所有 PHP 高手都看過吧,或許你不知道其實她是女的</li> </ul> <p>雖然沒有像 Lars Bak、Mike Pall 這樣在虛擬機領域的頂級專家,但如果這些大牛能齊心協力,寫個虛擬機還是問題不大的,那麼他們將面臨什麼樣的挑戰呢?接下來我們一一討論。 </p> <h3>規範是什麼? </h3> <p>自己寫PHP 虛擬機器要面臨的第一個問題就是PHP 沒有語言規範,很多版本間的語法還會不相容(甚至是小版本號,例如5.2.1 和5.2.3),PHP 語言規範究竟如何定義呢?來看一篇來自 IEEE 的說法:</p> <blockquote> <p>The PHP group claim that they have the ?nal say in the speci?cation of (the language) PHP. This groups speci?cation is an implementation, and there is no prose speci?cation or agreed validation suite.</p> </blockquote> <p>所以唯一的途徑就是老實去看 Zend 的實現,好在 HPHPc 中已經痛苦過一次了,所以 HHVM 能直接利用現成,因此這個問題並不算太大。 </p> <h3>語言還是擴充? </h3> <p>實作 PHP 語言不僅只是實現一個虛擬機器那麼簡單,PHP 語言本身還包括了各種擴展,這些擴展和語言是一體的,Zend 不辭辛勞地實現了各種你可能會用到的功能。如果分析 PHP 的程式碼,你會發現它的 C 程式碼除去空行註解後居然還有80+萬行,而你猜其中 Zend 引擎部分有多少?只有不到10萬行。 </p> <p>對開發者來說這不是什麼壞事,但對於引擎實現者來說就很悲劇了,我們可以拿Java 來進行對比,寫個Java 的虛擬機只需實現字節碼解釋及一些基礎的JNI 調用,Java 絕大部分內建函式庫都是用Java 實現的,所以如果不考慮性能優化,單從工作量看,實現PHP 虛擬機比JVM 要難得多,比如就有人用8千行的TypeScript 實現了一個JVM Doppio。 </p> <p>而對於這個問題,HHVM 的解決辦法很簡單,那就是只實現 Facebook 中用到的,而且同樣可以先用 HPHPc 中之前寫過的,所以問題也不大。 </p> <h3>實作 Interpreter</h3> <p>接下來是Interpreter 的實現,在解析完PHP 後會產生HHVM 自己設計的一種Bytecode,儲存在<code>~/.hhvm.hhbc(SQLite 檔案) 中以便重用,在執行Bytecode 時和Zend 類似,也是將不同的字節碼放到不同的函數中去實現(這種方式在虛擬機器中有個專門的稱呼:Subroutine threading)

Interpreter 的主體實現在bytecode.cpp 中,例如VMExecutionContext::iopAdd 這樣的方法,最終執行會根據不同類型來區分,例如add 操作的實現是在tv-arith.cpp 中,下面摘抄其中的一小段

<div class="blockcode"> <div id="code_oM7"><ol> <li>if (c2.m_type == KindOfInt64) return o(c1.m_data.num, c2.m_data.num);</li> <li>if (c2.m_type == KindOfDouble) return o(c1.m_data.num, c2.m_data.dbl);</li> </ol></div> <em onclick="copycode($('code_oM7'));">复制代码</em> </div>

正是因為有了Interpreter,HHVM 在對於PHP 語法的支持上比HPHPc 有明顯改進,理論上做到完全兼容官方PHP,但僅這麼做在性能並不會比Zend 好多少,由於無法確定變數類型,所以需要加上類似上面的條件判斷語句,但這樣的程式碼不利於現代CPU 的執行最佳化,另一個問題是資料都是boxed 的,每次讀取都需要透過類似m_data.numm_data.dbl 的方法來間接取得。

對於這樣的問題,就得靠 JIT 來優化了。

實現 JIT 及最佳化

首先值得一提的是 PHP 的 JIT 之前並非沒人嘗試過:

  • 2008 年有人用 LLVM 實驗過,結果還比原來慢了 21 倍。 。 。
  • 2010 年 IBM 日本研究院基於他們的 JVM 虛擬機程式碼開發了 P9,性能是官方 PHP 的 2.5 到 9.5 倍,可以看他們的論文 Evaluation of a just-in-time compiler retrofitted for PHP。
  • 2011 年 Andrei Homescu 是基於 RPython 開發過,也寫了篇論文 HappyJIT: a tracing JIT compiler for PHP,但測試結果有好有壞,並不理想。

那麼究竟什麼是 JIT?如何實作一個 JIT?

在動態語言中基本上都會有個eval 方法,可以傳給它一段字串來執行,JIT 做的就是類似的事情,只不過它要拼接不是字串,而是不同平台下的機器碼,然後進行執行,但如何用C 來實現?可以參考 Eli 寫的這個入門例子,以下是文中的一段程式碼:

<div class="blockcode"> <div id="code_JSG"><ol> <li>unsigned char code[] = {</li> <li> 0x48, 0x89, 0xf8, // mov %rdi, %rax</li> <li> 0x48, 0x83, 00x83, 00x // add $4, %rax</li> <li> 0xc3 // ret</li> <li>};</li> <li>memcpy(m, code, sizeof(code));</li> </ol></div> <em onclick="copycode($('code_JSG'));">複製代碼</em> </div>

然而手工編寫機器碼很容易出錯,所以最好的有一個輔助的庫,比如的Mozilla 的Nanojit 以及LuaJIT 的DynASM,但HHVM 並沒有使用這些,而是自己實現了一個只支持x64 的(另外還在嘗試用VIXL 來產生ARM 64 位元的),透過mprotect 的方式讓程式碼可執行。

但為什麼 JIT 程式碼會更快?你可以想想其實用 C++ 寫的程式碼最後編譯出來也是機器碼,如果只是將同樣的程式碼手動轉成了機器碼,那和 GCC 產生出來的有什麼差別呢?雖然前面我們提到了一些針對CPU 實作原理來最佳化的技巧,但在JIT 中更重要的最佳化是根據類型來產生特定的指令,從而大幅減少指令數和條件判斷,下面這張來自TraceMonkey 的圖對此進行了很直觀的對比,後面我們將看到HHVM 中的具體例子:

HHVM 是如何提升 PHP 性能的?

HHVM 先透過 interpeter 來執行,那它會在時候使用 JIT 呢?常見的 JIT 觸發條件有 2 種:

  • trace:記錄循環執行次數,如果超過一定數量就對這段程式碼進行 JIT
  • method:記錄函數執行次數,如果超過一定數量就對整個函數進行 JIT,甚至直接 inline

關於這兩種方法哪種更好在Lambada 上有個帖子引來了各路大神的討論,尤其是Mike Pall(LuaJIT 作者) 、Andreas Gal(Mozilla VP) 和Brendan Eich(Mozilla CTO)都發表了許多自己的觀點,推薦大家圍觀,我這裡就不獻醜了。

它們之間的差異不只是編譯範圍,還有很多細節問題,例如對局部變數的處理,在這裡就不展開了

但 HHVM 並沒有採用這兩種方式,而是自創了一個叫 tracelet 的做法,它是根據類型來劃分的,看下面這張圖

HHVM 是如何提升 PHP 性能的?

可以看到它將一個函數劃分為了3 部分,上面2 部分是用於處理$k<code>$k 為整數或字符串兩種不同情況的,下面的部分是返回值,所以看起來它主要是根據類型的變化情況來劃分JIT 區域的,具體是如何分析和拆解Tracelet 的細節可以查看Translator.cpp 中的Translator::analyze<code>Translator::analyze 方法,我還沒空看,這裡就不討論了。

當然,要實現高效能的JIT 還需進行各種嘗試和優化,例如最初HHVM 新增的tracelet 會放到前面,也就是將上圖的A 和C 調換位置,後來嘗試了一下放到後面,結果性能提示了14%,因為測試發現這樣更容易提前命中響應的類型

JIT 的執行過程是先將HHBC 轉成SSA (hhbc-translator.cpp),然後對SSA 上做優化(比如Copy propagation),再生成本地機器碼,比如在X64 下是由translator-x64. cpp 實現的。

我們用一個簡單的例子來看看 HHVM 最終產生的機器碼是怎麼樣的,例如下面這個 PHP 函數:

<code class="php language-php" data-lang="php"><div class="blockcode"> <div id="code_B9S"><ol> <li><?php<li>function a($b){<li> echo $b + 2;<li>}</ol></div><em onclick="copycode($('code_B9S'));">复制代码</em></div>

function a($b){<div class="blockcode"> echo $b + 2;<div id="code_ZLy">}<ol><li><em onclick="copycode($('code_B9S'));">複製程式碼<li><li><li> <li>編譯後是這個樣子:<li> <li><li><li><li><li>mov rcx,0x7200000<li>mov rdi,rbp<li>mov rsi,rbx<li>mov rdx,rbp<li>mov rsi,rbx<li>mov rdx,rbp<li>mov rsi,rbx<li>mov rdx,0x20<hox ::traceCallback(HPHP::ActRec*, HPHP::TypedValue*, 長, void*)><li>cmp BYTE PTR [rbp-0x8],0xa<li>jne 0xae00306<li>; 前面是檢查參數是否有效<li><li>mov rcx,QWORD PTR [rbp-0x10] ; 這裡將%rcx 被賦值為1了<li>mov edi,0x2 ; 將%edi(也就是%rdi 的低32位元)賦值為2 <li>add rdi,rcx ; 加%rcx<li>call 0x2131f1b <HPHP::print_int(long)> ; 呼叫print_int 函數,這時第一個參數%rdi 的值已經是3了</ol></div>; 後面暫不討論<em onclick="copycode($('code_ZLy'));">mov BYTE PTR [rbp+0x28],0x8</em>lea rbx,[rbp+0x20]</div>test BYTE PTR [r12],0xff<🎜>jne 0xae0032a< QWORD PTR [rbp+0x8]<🎜>mov rbp,QWORD PTR [rbp+0x0]<🎜>mov rdi,rbp<🎜>mov rsi,rbx<🎜>mov rdx,QWORD PTR [rsp]<vp]d <HPHP::JIT::traceRet(HPHP::ActRec*, HPHP::TypedValue*, void*)><🎜>ret <🎜><🎜><🎜>複製程式碼<🎜><🎜>

而 HPHP::print_int 函數的實作是這樣的:

<div class="blockcode"><div id="code_K6f"><ol><code class="c++ language-c++" data-lang="c++"><div class="blockcode"><div id="code_K6f"><ol><li>void print_int(int64_t i) {<li> char buf[256];<li> snprintf(buf, 256, "%" PRId64, i);<li> echo(buf);<li> TRACE(1, "t-x64 output(int): %" PRId64 "n", i);<li>}</ol></div><em onclick="copycode($('code_K6f'));">复制代码</em></div>void print_int(int64_t i) {

char buf[256];int64_t snprintf(buf, 256, "%" PRId64, i);

echo(buf);

TRACE(1, "t-x64 output(int): %" PRId64 "n", i);

}<div class="blockcode"><div id="code_K70"><ol><li>-v Eval.JitWarmupRequests=0</ol></div><em onclick="copycode($('code_K70'));">复制代码</em></div>複製程式碼

可以看到HHVM 編譯出來的程式碼直接使用了int64_t</h3>,避免了interpreter 中需要判斷參數和間接取資料的問題,從而明顯提升了效能,最終甚至做到了和C 編譯出來的程式碼區別不大。 <p> </p>需要注意:HHVM 在 server mode 下,只有超過12個請求就才會觸發 JIT,啟動過 HHVM 時可以透過加上以下參數來讓它首次請求就使用 JIT:<code class="php language-php" data-lang="php"><div class="blockcode"><div id="code_biL"><ol><li><?hh<li>class Point2 {<li> public float $x, $y;<li> function __construct(float $x, float $y) {<li> $this->x = $x;</li> <li> $this->y = $y;</li> <li> }</li> <li>}</li> <li>//来自:https://raw.github.com/strangeloop/StrangeLoop2013/master/slides/sessions/Adams-TakingPHPSeriously.pdf</li> </ol></div> <em onclick="copycode($('code_biL'));">复制代码</em> </div> <div class="blockcode"><div id="code_K70"> <ol><p>-v Eval.JitWarmupRequests=0</p></ol> <code>float複製程式碼

所以在測試效能時需要注意,執行一兩次就拿來對比是看不出效果的。

類型推導很麻煩,還是逼迫程式設計師寫清楚吧

JIT 的關鍵是猜測類型,因此某個變數的類型要是老變就很難優化,於是HHVM 的工程師開始考慮在PHP 語法上做手腳,加上類型的支持,推出了一個新語言- Hack (吐槽一下這名字真不利於SEO),它的樣子如下:

<div class="blockcode"><div id="code_biL"> <ol> <?hh <p>class Point2 { public float $x, $y;</ol> <ul> function __construct(float $x, float $y) {<li> $this->x = $x;</li> $this->y = $y;<li> }</li>}<li>//來自:https://raw.github.com/strangeloop/StrangeLoop2013/master/slides/sessions/Adams-TakingPHPSeriously.pdf</li> <em onclick="copycode($('code_biL'));">複製程式碼</em> </ul> <p> </p>注意到<code>float<p> 關鍵字了麼?有了靜態類型可以讓 HHVM 更好地優化效能,但這也意味著和 PHP 語法不相容,只能使用 HHVM。 </p> <h2>其實我個人認為這樣做最大的優點是讓程式碼更加易懂,減少無意的犯錯,就像Dart 中的可選類型也是這個初衷,同時還方便了IDE 識別,據說Facebook 還在開發一個基於Web 的IDE,能協同編輯程式碼,可以期待一下。 </h2> <ul>你會使用 HHVM 麼? <li> </li>總的來說,比起之前的HPHPc,我認為HHVM 是值得一試的,它是真正的虛擬機,能夠更好地支援各種PHP 的語法,所以改動成本不會更高,而且因為能無縫切換到官方PHP 版本,所以可以同時啟動FPM 來隨時待命,HHVM 還有FastCGI 接口方便調用,只要做好應急備案,風險是可控的,從長遠來看是很有希望的。 <li> </li>效能究竟能提升多少我無法確定,需要拿自己的業務代碼來進行真實測試,這樣才能真正清楚HHVM 能帶來多少收益,尤其是對整體性能提升到底有多少,只有拿到這個數據才能做決策。 <li> </li>最後整理一下可能會遇到的問題,有計畫使用的可以參考:<li> </li> <li>擴展問題:如果用到了 PHP 擴展,肯定是要重寫的,不過 HHVM 擴展寫起來比 Zend 要簡單的多,具體細節可以看 wiki 上的例子。 </li> <li>HHVM Server 的穩定性問題:這種多執行緒的架構運作一段時間可能會出現記憶體外洩問題,或是某個沒寫好的PHP 直接導致整個行程掛掉,所以需要注意這方面的測試和容災措施。 </li> <li>問題修復困難:HHVM 在出現問題時將比 Zend 難修復,尤其是 JIT 的程式碼,只能期望它比較穩定了。 </li> <li> </li>P.S. 其實我只了解基本的虛擬機器知識,也沒寫過幾行PHP 程式碼,很多東西都是寫這篇文章時臨時去找資料的,由於時間倉促水平有限,必然會有不正確的地方,歡迎大家評論賜教:)<li> </li>2014年1月補充:目前 HHVM 在鄙廠的推廣勢頭很不錯,推薦大家在2014年嘗試一下,尤其是現在兼容性測試已經達到98.58%了,修改成本進一步減小。 <li> </li>引用</ul>

Keith Adams 在 HN 上的蛛絲馬跡
How Three Guys Rebuilt the Foundation of Facebook
PHP on the Metal with HHVM

Making HPHPi Faster HHVM Optimization Tips The HipHop Virtual Machine (hhvm) PHP Execution at the Speed of JIT Julien Verlaguet, Facebook: Analyzing PHP statically Speeding up PHP-based development with HHVM Adding an opcode to HHBC
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn