PHP 8 效能調校:OpCache 與 JIT 詳解
您的 PHP 8 應用程式在高負載下顯得遲緩。您已優化查詢、加入快取,但回應時間仍然落後。罪魁禍首可能是 PHP 本身的執行開銷。兩個強大的功能——OpCache 和 JIT——可以大幅加速您的程式碼,但前提是配置正確。本指南將解釋它們的運作原理,以及如何針對實際工作負載進行調校。
什麼是 OpCache 以及為何它很重要
PHP 是一種解釋型語言:每個請求通常會先解析並編譯您的原始檔為位元碼,然後才執行。OpCache 會將編譯後的位元碼儲存在共享記憶體中,因此後續請求可以跳過解析和編譯步驟。結果呢?更低的 CPU 使用率和更快的回應時間。
在許多生產環境中,OpCache 預設是啟用的,但預設設定較為保守。對其進行調校,可為 CPU 密集型應用程式帶來 2 到 3 倍的吞吐量提升。
關鍵 OpCache 配置指令
- opcache.enable:設為 1 以啟用。(生產環境預設為 1,CLI 環境預設為 0,除非另行覆寫。)
- opcache.memory_consumption:共享記憶體大小,單位為 MB。從 128 MB 開始;如果看到
opcache.memory_usage很高,則增加此值。 - opcache.max_accelerated_files:快取的最大檔案數量。設為大於您 PHP 檔案總數的質數(例如 10007)。
- opcache.validate_timestamps:設為 1 時,PHP 會檢查檔案時間戳以偵測變更。在生產環境中設為 0 以避免 stat 呼叫;部署後您必須手動清除快取。
- opcache.revalidate_freq:如果 validate_timestamps=1,檢查時間戳的頻率(秒)。開發環境設為 0,生產環境設為 60 或更高。
- opcache.interned_strings_buffer:用於駐留字串(interned strings)的記憶體(MB)。對於大型應用程式,增加到 16 或 32。
- opcache.fast_shutdown:在 PHP 7.2+ 中已棄用,在 PHP 8.0 中已移除。請忽略。
- opcache.preload:預載入指令碼的路徑(PHP 7.4+)。預載入會在啟動時編譯並快取檔案,消除關鍵類別的每個請求開銷。
生產環境推薦的 OpCache 設定
; php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.interned_strings_buffer=32
opcache.preload=/path/to/preload.php
opcache.preload_user=www-data
更改設定後,重新啟動 PHP-FPM。使用 opcache_get_status() 監控以檢查命中率和記憶體使用情況。
了解 PHP 8 中的 JIT
JIT(即時編譯)讓 OpCache 更進一步:它在執行時將位元碼編譯為原生機器碼。這可以顯著加速 CPU 密集型任務,如數學運算,但對於典型的 I/O 密集型網頁請求(資料庫、檔案系統、網路)幫助不大。
JIT 是 OpCache 的一部分,因此您必須先啟用 OpCache。在 PHP 8 中,JIT 透過 opcache.jit 和 opcache.jit_buffer_size 進行配置。
JIT 配置指令
- opcache.jit:控制 JIT 模式。使用
tracing(預設)或function。該值是一個 4 位數的 CRTO 代碼:CRTO,其中 C=CPU 特定優化,R=暫存器分配,T=觸發,O=優化等級。對於大多數應用程式,opcache.jit=tracing就足夠了。 - opcache.jit_buffer_size:用於 JIT 程式碼的記憶體,單位為位元組。從 64M 或 128M 開始。如果設為 0,則停用 JIT。
- opcache.jit_hot_loop、opcache.jit_hot_func、opcache.jit_hot_return、opcache.jit_hot_side_exit:熱點程式碼偵測的閾值。預設值通常沒問題。
推薦的 JIT 設定
opcache.jit=tracing
opcache.jit_buffer_size=128M
注意:JIT 僅在啟用 OpCache 時才能運作。在 CLI 中,您可能需要設定 opcache.enable_cli=1 來測試 JIT。
OpCache 與 JIT:何時使用哪一個
| 功能 | OpCache | JIT |
|---|---|---|
| 主要優點 | 快取編譯後的位元碼 | 將位元碼編譯為原生程式碼 |
| 最適合 | 所有 PHP 應用程式 | CPU 密集型、長時間執行的指令碼 |
| 對 I/O 密集型應用程式的影響 | 高(減少解析/編譯) | 低至無 |
| 記憶體開銷 | 中等 | 額外的緩衝區 |
| 複雜度 | 低 | 中 |
逐步調校指南
- 啟用 OpCache,使用上述推薦設定。
- 監控 OpCache,使用
opcache_get_status()或 OpCache GUI 等工具。目標是命中率高於 99%。 - 調整記憶體,如果
opcache.memory_usage接近上限。 - 考慮預載入,適用於大型框架(Laravel、Symfony)。建立一個預載入指令碼,載入經常使用的類別。
- 啟用 JIT,僅當您的應用程式是 CPU 密集型時。在有無 JIT 的情況下進行測試以衡量影響。
- 基準測試,使用
ab、wrk或siege等工具。比較每秒請求數和延遲。 - 逐步部署變更,並監控錯誤日誌以發現問題。
常見陷阱與最佳實踐
- 不要在開發環境中停用 validate_timestamps:您會浪費時間納悶為什麼程式碼變更沒有生效。
- 部署時清除 OpCache:如果 validate_timestamps=0,您必須重置 OpCache(例如,重新啟動 PHP-FPM 或呼叫
opcache_reset())。 - JIT 不是萬靈丹:對於典型的 CRUD 應用程式,僅 OpCache 就能提供大部分效能提升。
- 注意記憶體:JIT 緩衝區和 OpCache 記憶體會增加 PHP 的記憶體佔用。確保您的伺服器有足夠的 RAM。
- 謹慎使用預載入:預載入的檔案會一直留在記憶體中;避免預載入所有內容。
常見問題
JIT 能提升所有 PHP 應用程式的效能嗎?
不能。JIT 對 CPU 密集型任務有益,例如複雜計算或資料處理。對於 I/O 密集型網頁應用程式(資料庫查詢、API 呼叫),增益很小。僅 OpCache 通常就能提供最大的速度提升。
如何知道 OpCache 是否正常運作?
檢查 phpinfo() 中的 OpCache 狀態,或在指令碼中呼叫 opcache_get_status()。尋找 opcache_enabled => true 以及相對於 misses 的高 hits 計數。
我可以在 PHP 7 中使用 JIT 嗎?
不行。JIT 是在 PHP 8.0 中引入的。PHP 7 僅支援 OpCache。如果您使用的是 PHP 7,請專注於 OpCache 調校,並考慮升級到 PHP 8 以獲得 JIT 和其他效能改進。
準備好分析您伺服器的效能了嗎?查看我們的 Nginx Log Analyzer,從您的存取日誌中獲得見解並找出瓶頸。