網(wǎng)站優(yōu)化之PHP并發(fā)性能性能提升104%調(diào)優(yōu)實(shí)戰(zhàn)
2019-05-28
2012 年有一篇很火的博客:PHP: a fractal of bad design。作者在文中對(duì) PHP 大張撻伐,幾乎就差說(shuō)這是反人類(lèi)的設(shè)計(jì)了。第一次讀到此文時(shí),我正在一個(gè)惡心的地方處理很多遺留的 PHP 項(xiàng)目。讀完文章時(shí),我開(kāi)始思考是否要辭職去做一些與編程完全不同的事情。
幸運(yùn)的是,此后不久我就換了工作,而且 PHP 從 5.* 開(kāi)始也成長(zhǎng)了很多。今天,我想對(duì)那些不再使用 PHP 編程,或者被遺留項(xiàng)目困擾的人說(shuō)點(diǎn)什么。
Spoiler:PHP 跟其他編程語(yǔ)言一樣,都有點(diǎn)自己的小毛病。很多核心函數(shù)的方法簽名不一致,配置設(shè)置仍然不清不楚,仍然有很多開(kāi)發(fā)人員在寫(xiě)蹩腳的代碼——因?yàn)樗麄儽仨氝@樣做,或者說(shuō),他們沒(méi)有更好的方法。
但今天,我想說(shuō)的是 PHP 好的一面:看看 PHP 的成長(zhǎng),共同探討一下如何編寫(xiě)干凈且可維護(hù)的 PHP 代碼。希望大家可以暫時(shí)把偏見(jiàn)放進(jìn)肚子里,哪怕只有幾分鐘。等我說(shuō)完,你可以把它們?cè)倌贸鰜?lái),但是你一定會(huì)驚訝于過(guò)去幾年里 PHP 的成長(zhǎng)。
快速閱讀
PHP 每年都在積極開(kāi)發(fā)新版本
自 PHP 5 時(shí)代以來(lái),性能至少翻了一番,甚至有可能是曾經(jīng)的三倍
有極其活躍的框架、包和平臺(tái)生態(tài)系統(tǒng)
過(guò)去幾年增加了很多新特性,語(yǔ)言也在不斷發(fā)展中
像靜態(tài)分析器這樣的工具已經(jīng)成熟,并且會(huì)越來(lái)越多
更新:有人讓我展示一些代碼示例,這當(dāng)然可以!下面有兩個(gè)例子:一個(gè)是我比較喜歡的項(xiàng)目,是用 PHP 和 Laravel 語(yǔ)言編寫(xiě)的;還有一個(gè)是我們辦公室維護(hù)的幾百個(gè) OSS 包的列表。代碼地址如下:
https://github.com/brendt/aggregate.stitcher.io
https://spatie.be/opensource/packages
那我們開(kāi)始吧。
歷史背景
首先,我們快速回顧一下 PHP 的發(fā)布周期?,F(xiàn)在的 PHP 版本是 7.3,預(yù)計(jì) 2019 年底將發(fā)布 7.4,然后下個(gè)版本將是 PHP 8.0。
自 5.* 時(shí)代之后,其核心團(tuán)隊(duì)努力保持著一年一版本的發(fā)布周期,并在過(guò)去四年中成功做到了這一點(diǎn)。
一般來(lái)說(shuō),每一個(gè)新版本都有兩年的有效支持期,然后再用一年來(lái)做「安全修復(fù)」。這么做的目的是鼓勵(lì) PHP 開(kāi)發(fā)人員盡可能使用最新版本,因?yàn)槊磕甑男∩?jí)比從 5.4 跳到 7.0 版本要容易得多。
PHP 的版本時(shí)間表如下:
其中,PHP 5.6 是 5.*時(shí)代的最新版本,它的下一個(gè)版本就是 7.0。如果您想知道 PHP 6 發(fā)生了什么,可以收聽(tīng) PHP 圓桌播客 :
https://www.phproundtable.com/episode/what-happened-to-php-6
了解這些之后,我們可以進(jìn)一步探討關(guān)于 PHP 的常見(jiàn)誤解了。
PHP 性能
5.* 時(shí)代的 PHP 性能充其量也不過(guò)是平均水平,但是在 7.0 中,PHP 核心的大部分內(nèi)容都被完全重寫(xiě),性能也因此提高了兩到三倍。
光說(shuō)不練假把式,我們用基準(zhǔn)測(cè)試結(jié)果說(shuō)話(huà)。有人對(duì) PHP 的性能進(jìn)行過(guò)基準(zhǔn)測(cè)試,這些測(cè)試被很好地記錄在了 Kinsta 上:
https://kinsta.com/blog/php-benchmarks/
自從 7.0 出現(xiàn)以后,PHP 的性能一直處于上升期。PHP web 應(yīng)用的性能與其他語(yǔ)言的 web 框架相當(dāng) (在某些情況下甚至更好)。不信可以看看這個(gè)通用基準(zhǔn)測(cè)試包:
https://github.com/thebenchmarker/webframeworks
PHP 框架雖然沒(méi)辦法做到比 C 和 Rust 更好,但是它比 Rails 或 Django 要好得多,并且可以與 ExpressJS 相媲美。
框架和生態(tài)系統(tǒng)
說(shuō)到框架,PHP 已經(jīng)不再只是 WordPress 了。作為一名專(zhuān)業(yè)的 PHP 開(kāi)發(fā)人員,我想說(shuō)的是:WordPress 根本不能代表現(xiàn)在的生態(tài)系統(tǒng)。
一般有兩個(gè)主要的 web 應(yīng)用程序框架和一些小框架,比如 Symfony 和 Laravel。當(dāng)然,還有 Zend、Yii、Cake、Code Igniter 等,但是只有這兩種主要的框架才能代表如今的 PHP。
這兩個(gè)框架都有一個(gè)包含大量包和產(chǎn)品的生態(tài)系統(tǒng)。從管理面板和 CRM 到獨(dú)立的軟件包、CI、profiler,眾多如 web sockets 服務(wù)器、隊(duì)列管理器、支付集成這樣的服務(wù)...... 可以拿得出手的東西太多了。
不過(guò),這些框架是用于實(shí)際開(kāi)發(fā)的。如果你需要純粹的內(nèi)容管理,像 WordPress 和 CraftCMS 這樣的平臺(tái)只會(huì)越來(lái)越好。
測(cè)試 PHP 生態(tài)系統(tǒng)當(dāng)前狀態(tài)的一種方法是查看 Packagist,它是 PHP 的主要 package 存儲(chǔ)庫(kù)。它呈指數(shù)級(jí)增長(zhǎng),每天大約有 2500 萬(wàn)次的下載量。公平地說(shuō),PHP 生態(tài)系統(tǒng)已經(jīng)不再是過(guò)去的小輸家了。
下面的圖表,列出了包和版本的數(shù)量隨時(shí)間的變化。
除了應(yīng)用程序框架和 CMS,近年來(lái)異步框架也逐步興起。
這些框架和服務(wù)器是用 PHP 或其他語(yǔ)言編寫(xiě)的,通過(guò)這些框架,用戶(hù)可以實(shí)現(xiàn)真正的異步 PHP。Swoole、Amp 和 ReactPHP 都是很好的例子。
自從我們進(jìn)入異步世界以來(lái),像 web sockets 和具有大量 IO 的應(yīng)用程序之類(lèi)的東西已經(jīng)與 PHP 世界息息相關(guān)。
在內(nèi)部郵件列表(內(nèi)核開(kāi)發(fā)人員討論如何開(kāi)發(fā)該語(yǔ)言的地方)上也有關(guān)于將 libuv 添加到內(nèi)核的討論。
語(yǔ)言本身
雖然 async 和 await 功能都還不能用,但是在過(guò)去幾年里,PHP 語(yǔ)言本身已經(jīng)做了很多改進(jìn)。下面列出了 PHP 的部分新特性:
Short Closures
Null coalescing operator
Trait
Typed properties
Spread operator
JIT compiler
FFI
Anonymous classes
Return type declarations
Contemporary cryptography
Generators
除了語(yǔ)言特性,我們也應(yīng)該看一下語(yǔ)言的發(fā)展過(guò)程。雖然社區(qū)也會(huì)提出 RFCs,但一個(gè)活躍的核心志愿團(tuán)隊(duì)才是推動(dòng)語(yǔ)言的發(fā)展的根本。
這些 RFCs 會(huì)在「內(nèi)部」郵件列表中進(jìn)行討論。在添加新的語(yǔ)言特性之前,必須進(jìn)行投票,獲得至少 2/3 支持的 RFC 才能被寫(xiě)入內(nèi)核。
大概有 100 個(gè)人有投票權(quán),雖然他們不必對(duì)每個(gè) RFC 都進(jìn)行投票。這些人中必須包括核心團(tuán)隊(duì)的成員,因?yàn)樗麄円S護(hù)代碼庫(kù)。剩下的投票者主要是從 PHP 社區(qū)中挑選出來(lái)的,這些人包括 PHP 文檔的維護(hù)者、整個(gè) PHP 項(xiàng)目的貢獻(xiàn)者以及 PHP 社區(qū)中的杰出開(kāi)發(fā)人員。
雖然大多數(shù)核心開(kāi)發(fā)都是在自愿的基礎(chǔ)上完成的,但是作為核心 PHP 開(kāi)發(fā)人員之一,Nikita Popov 最近已被 JetBrains 聘用,成為了全職的 PHP 開(kāi)發(fā)者。另外,Linux 基金會(huì)最近也決定投資 Zend framework。這樣的雇傭和收購(gòu)確保了 PHP 未來(lái)發(fā)展的穩(wěn)定性。
工具包
除了程序內(nèi)核本身,PHP 工具包的數(shù)量也在不斷增加。靜態(tài)分析器 Psalm(由 Vimeo 創(chuàng)建)、Phan 和 PHPStan 都是很好的例子。
這些工具可以對(duì) PHP 代碼做靜態(tài)分析,并會(huì)報(bào)告任何類(lèi)型的錯(cuò)誤、可能的 bug 等。在某種程度上,它們的功能幾乎可以趕上 TypeScript 了,不過(guò)目前這種語(yǔ)言還無(wú)法實(shí)現(xiàn)源到源編譯,因此不允許使用自定義語(yǔ)法。
盡管這意味著我們需要依賴(lài) docblock,但 PHP 的最初創(chuàng)建者 Rasmus Lerdorf 確實(shí)提到了向內(nèi)核添加靜態(tài)分析引擎的想法。這個(gè)想法潛力巨大,但這是一項(xiàng)艱巨的任務(wù)。
為了像 JavaScript 那樣實(shí)現(xiàn)源到源編譯,PHP 開(kāi)發(fā)者們也一直努力在用戶(hù)端擴(kuò)展 PHP 語(yǔ)法。一個(gè)名為 Pre 的項(xiàng)目就在做這樣的事:將新的 PHP 語(yǔ)法轉(zhuǎn)換為普通的 PHP 代碼。
雖然 JavaScript 中已經(jīng)實(shí)現(xiàn)了這個(gè)想法,但是只有提供合適的 IDE 和靜態(tài)分析支持,它才能在 PHP 中工作。這個(gè)想法很有意思,但它還需要不斷成長(zhǎng),才有可能成為「主流」。
結(jié)語(yǔ)
說(shuō)了這么多,你仍然可以吐槽說(shuō) PHP 是一種蹩腳的語(yǔ)言。雖然它還是有一些缺點(diǎn)和 20 年的遺留問(wèn)題,但我仍然熱愛(ài)這門(mén)語(yǔ)言。
以我的經(jīng)驗(yàn)來(lái)看,我能夠?qū)懗隹煽恳拙S護(hù)且高質(zhì)量的軟件。我和客戶(hù)對(duì)最終的結(jié)果也都是滿(mǎn)意的。
雖然使用 PHP 還會(huì)有一些亂七八糟的事情,但如果使用得當(dāng),我認(rèn)為它還是一個(gè)不錯(cuò)的網(wǎng)絡(luò)開(kāi)發(fā)選擇。