abstract:在 Tumblr,我們一直在尋找新方法來提高網(wǎng)站的性能。 這意味著在關鍵路徑大量使用緩存,測試新的 CDN 配置或升級底層軟件。最近,在團隊的努力下,我們將整個 Web 服務器從 PHP 5 升級到 PHP 7,整個升級過程非常有意思,因此通過本文分享如下。升級的過程這一切都開始于 2015 年秋天一個 hackday 項目。@oli 和 @trav 在 Tumblr 運行一個 PHP 7 rc
在 Tumblr,我們一直在尋找新方法來提高網(wǎng)站的性能。 這意味著在關鍵路徑大量使用緩存,測試新的 CDN 配置或升級底層軟件。
最近,在團隊的努力下,我們將整個 Web 服務器從 PHP 5 升級到 PHP 7,整個升級過程非常有意思,因此通過本文分享如下。
升級的過程
這一切都開始于 2015 年秋天一個 hackday 項目。@oli 和 @trav 在 Tumblr 運行一個 PHP 7 rc 版本。在那時候,很多 PHP 擴展都還不支持PHP 7,但有非官方的分支保證實驗性支持。盡管這樣,Tumblr 已經(jīng)可以運行在 PHP7 上了!
今年春天,Tumblr 可以更加穩(wěn)定的運行在 PHP7 上,我們決定開始升級。我們做的第一件事是打包新版本,以便更容易安裝并保證一致。與此同時,我們將內(nèi)部 PHP 擴展移植到新版本,所以一切都準備好了。
我們編寫了一個可以升級(或降級)服務器的小腳本。然后,在春季及夏季,一直都在運行測試并進行性能監(jiān)測和評估。隨著時間推移,我們開始在更多開發(fā)人員日常使用的機器里運行PHP 7。
最后,在 8 月底,我們對測試結(jié)果感到滿意,于是將 PHP 7 替換到我們一小部分生產(chǎn)服務器。兩個星期后,所有線上服務器都已更新到 PHP7。
測試與持續(xù)集成
當進行這樣的升級時,用測試以確保代碼正確運行是非常重要的,我們有幾個方法。
在這個項目中,我們使用 Phan 尋找代碼庫中與 PHP 7 不兼容的代碼。
Phan:https://github.com/etsy/phan
我們還有一套單元和集成測試,幫助我們識別有問題的模塊。 由于項目開發(fā)還在進行中,我們需要確保沒有添加 PHP7 不兼容的新代碼,所以我們設置了持續(xù)集成的任務,同時在 PHP5 和 PHP7 環(huán)境下運行所有測試。
升級結(jié)果
最終的結(jié)果是什么? 性能和語言特性對我們來說是最重要的兩個結(jié)果。
性能
當我們在第一批服務器上運行 PHP7 時,我們非常密切地關注各種性能監(jiān)控圖表,以確保運行順利。 正如我們上面提到的,我們正在進行性能改進,實際上的升級結(jié)果是非常驚人的, 延遲減少一半,并且服務器上的 CPU 負載降低了 50% 或者更多。不但頁面響應速度提高了一倍,而且只使用了一半的 CPU 資源。
語言特性
除此之外,PHP 7 也帶來了很多有趣的新功能。 一些亮點是:
標量類型提示:PHP 歷史版本在類型安全方面相當差,PHP 7 引入標量類型提示(Scalar type),確保傳遞的值符合特定類型(字符串,bool,int,float等)。
返回類型聲明:現(xiàn)在,使用 PHP 7,函數(shù)可以有顯式返回類型。 這減少了對樣板代碼和手動檢查函數(shù)返回值的需求。
匿名類:與匿名函數(shù)(閉包)非常類似,匿名類在運行時構(gòu)建,可以模擬類/接口甚至擴展其他類。 這些對于像日志類這樣的實用對象非常有用,并且在單元測試中非常有用。
各種安全和性能增強。
總結(jié)
PHP7 相當棒。
以下是國外網(wǎng)站一些網(wǎng)友評論。
jsjohnst :
我沒有參與這個升級過程,但在基于我對 Tumblr(過去在那里工作了 3 年)代碼庫的了解,以及個人對 PHP 的背景(一直是 PHP 貢獻者?13 年),性能提升有 95% 的可能性與 PHP7 相關。 Chorus (Tumblr 內(nèi)部基于的框架)中使用的許多模式和在代碼庫,都會在 PHP7 內(nèi)部的變化中受益匪淺。
tyingq:
從 PHP5.x 切換到 PHP7 時,在響應時間,TPS 和內(nèi)存使用方面的顯著改進
https://www.symfony.fi/entry/symfony-benchmarks-php-56-hhvm-and-php-7
uses:
我們使用的 PaaS 云平臺最近升級了一個 PHP 7。
對于運行 Bolt 的網(wǎng)站(一個PHP CMS,它大量使用自動加載類),我們看到性能提高了 45% ~ 55%。 對于 Wordpress,它是約 30 ~ 40%。
bkanber :
我覺得也可能是因為 PHP7 默認啟用了 opcache,而之前并沒有啟用。
也就是說,更快的解析器和 intepreter 也會做更快的自動加載,所以即使不是opcache,也可能是憑借自動加載類被解釋得更快。
nikic:
我們在 7.1 版中 perf 顯示在實際應用中沒有看到顯著的收益(對計算密集型代碼有一些改進,比如循環(huán)中的計算)。
JIT 是否會對應用程序帶來重大改進尚不清楚,我們希望如此。
boulos:
對,我很久以前也對比過,大多數(shù)的性能改進來自于運行時的 C 代碼改進,比如在實際運行的系統(tǒng)中,產(chǎn)生較少的字符串副本非常關鍵。這是你在 PHP 7 改進中首先看到的。
使用 PHP 從字節(jié)碼解釋器生成 x86 機器碼將意味著在你不結(jié)束“跳出”的地方,你應該看到更接近 C 代碼性能(JavaScript,Python 等同樣如此)。PHP7 的標量類型提示和其他一些小調(diào)整(有意義的)應該使 jit 編程一個更容易的任務(對比從 PHP 5.4 到 PHP7)。類型推理是非常有效的,在實踐中(見Paul Biggar對此的優(yōu)秀論文),在 PHP 程序中確實沒有那么多的多態(tài)性。函數(shù)的參數(shù)通常有一個或兩個類型,或者它們實際上是多態(tài)的并有跟多的變體。
progforlyfe
沒錯,最大的性能改進是來自類似 JIT 改進, 跟 HHVM 所做的工作類似。
tiffanyh:
我很困惑,PHP 7 現(xiàn)在沒有 JIT,但它的性能已經(jīng)與 HHVM(它有JIT)一致。
然后就是說 PHP 8(與JIT)將顯著快于 HHVM?
TazeTSchnitzel :
未必,這可能意味著很多 HHVM 的性能改進與 JIT 無關。