PHP 的性能猛獸 - Swoole

前言

PHP 發展至今已經 20 餘年,現今許多網站有相當高的比例都是以 PHP 所建構而成,然而一直以來 PHP 為人所詬病的就是他的效能問題。尤其是現今許多的開發框架雖然強大優雅,但同時也因為框架的複雜度讓 PHP 的效能更加倍放大來檢視,甚至成為許多人不選擇使用框架開發的原因。

雖然在新版的 PHP 7 中比起以往效能上有重大的突破,但在大多數人眼中 PHP 似乎始終都不是以效能為考量時的主要首選開發語言。但是接下來要介紹的 Swoole 可能會讓你重新定義 PHP,甚至更加倍地愛上他。

PHP 面對大流量或高效能需求時,也有許多優秀的解決方案,但不在本篇文章的主題內,故不細加說明。

Swoole 簡介

首先,Swoole 這個名字源自於作者起出的名字 sword-server,意即希望為廣大的 PHP 開發者創造出一把鋒利的劍,後來又參考 google 的字將sword-server做變形變成了 Swoole 這個名字。 

Swoole 並不是一個新的程式語言,他是一個以純 C 語言編寫的 PHP extension,簡單來說他有以下特點:

  • 純 C 語言編寫,所以性能超強
  • 事件驅動 (Event Driven)
  • 異步 I/O
  • 支援 異步/同步/協程 (Coroutine)
  • 支援 TCP/UDP/UnixSock 通信協定
  • 支援異步 Server 端和異步 Client 端
  • 支援多行程 (Process) 與多執行緒 (Thread)
  • 支援 IPv4 與 IPv6
  • 低 CPU 消耗與支援 daemon 模式

Swoole 是一個多行程模式的框架,當 Swoole 啟動時,一共會建立 2 + n + m 個行程,其 nWorker 數mTaskWorker 數2 為一個 Master 行程和一個 Manager 行程,架構圖如下: swoole-model

列了那麼多特點,簡單來說,就是 Swoole 能讓你的 PHP 馬上提升好幾個等級,能達到原生 PHP 不支援的許多功能,雖然 Swoole 並不是第一個支援異步的方案,而 PHP 本身也能使用一些方式達成異步,但是 Swoole 的效能在目前來說還沒有人能與其匹敵,更別說他除了異步還有以上那麼多優秀的功能。

異步開發

前面談到了異步,但異步對於效能有什麼幫助?近幾年 NodeJS 深受許多人喜愛,原因之一就是他的異步功能,而造就了他優秀的性能,以下為簡易 NodeJS 的異步流程: nodejs-async

傳統上來說,一個客戶端發起的 request 在伺服器端處理時會有很多 I/O 的操作,而 I/O 通常是最耗費時間的,但是伺服器端會等相關的 I/O 處理完才會一次回傳給客戶端結果,此時便呈現阻塞的 (Blocked) 狀態,一旦伺服器該請求未完全處理完,其他客戶端的請求就必須等待。

而異步能讓伺服器在 I/O 未處理完時就繼續處理下一個用戶端的請求,當前面的 I/O 處理完成時再回覆前次的請求,藉由這種方式充份地使用的伺服器的效能。

當然 NodeJS 的 V8 引擎和本身就能夠當作 Server 來服務,免去每次的 request 需要重複載入及編譯也是 NodeJS 效能的重要功臣。

NodeJS vs Swoole

既然 NodeJS 的性能如此優異,那 Swoole 相比之下還有哪些優勢呢?

  • Callback 函數更加靈活 所有的編譯式語言都是透過 callback 機制來達成異步的,包含C/C++、Java、Ruby、Python、Javascript,與 Javascript 相比,PHP 支援 4 種不同的 callback 寫法,讓你寫起來更加地有彈性。(請參照: 4種PHP回調函數風格)

  • 更優秀的效能 NodeJS 雖然在效能上相當不錯,但是 Swoole 是以純 C 語言編寫的,又 NodeJS 只支援單一程序單執行緒,而 Swoole 支援多程序多執行緒,所以效能上更加優秀。

以下效能評測以wrk 壓力測試工具NodeJSSwoole 進行測試,雙方 server 都只進行單純的印出資料作為回覆。

  • Node.js v4.2.6
wrk -t4 -c400 -d10s http://127.0.0.1:1337/  
Running 10s test @ http://127.0.0.1:1337/  
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.08ms    2.70ms 237.82ms   90.94%
    Req/Sec     6.05k   510.34     7.10k    91.00%
  240668 requests in 10.02s, 46.36MB read
Requests/sec:  24026.00  
Transfer/sec:      4.63MB  
  • PHP7.1+Swoole-v1.9.5
wrk -t4 -c400 -d10s http://127.0.0.1:1337/  
Running 10s test @ http://127.0.0.1:1337/  
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.46ms    1.42ms  27.96ms   85.66%
    Req/Sec    75.29k    36.43k  183.55k    72.75%
  3007806 requests in 10.06s, 605.25MB read
Requests/sec: 299103.32  
Transfer/sec:     60.19MB  

若單純以 RPS 數據作效能比較,Swoole 的處理速度大約是 NodeJS 的十倍之多,這樣的結果是相當令人驚豔的,Swoole 的誕生完全為 PHP 長期以來在性能上遭受的罵名扳回一城。

(評測資料來自於: PHP 7.1+ Swoole v1.9.5 vs Node.js Benchmark Test PHP7 + Swoole beats Node.js)

結論

總結來說,個人對於 Swoole 的評價相當的高,非常推薦給有興趣的人來嘗試,但是在這裡還是列出客觀上一些 Swoole 所面臨的劣勢:

  • 官方文件相當簡易,而且只有中文,缺乏定期維護
  • 儘管 Swoole 有中國的騰訊百度阿里巴巴等多家技術人員投入開發使用,但缺乏廣大的社群
  • 入門門檻較高,若要完整熟悉 Swoole 開發,必須擁有大量多執行緒開發UnixTCP的經驗與知識才能完全掌握
  • 不支援 Windows,除非裝上虛擬器執行 Linux 或是使用 CygWin (也建議只在開發用,不適合當 production server)
  • 網路上學習資源相對少,目前市面上也沒有相關的教學書籍可以參考

即便是這樣,如果你本身就熟悉 PHP,在效能上有所追求或是想嘗試不同的開發方式,還是相當推薦試試看 Swoole !

參考資源: Swoole 官方網站