核心優化原則
優化應基於剖析結果,而非直覺。使用 Xdebug/Blackfire 找出真正瓶頸,針對性調整。
1-10: 基礎語法與函數選擇
- 靜態方法化:可靜態則靜態,效能提升 4 倍。
- echo 優於 print,多參數 `echo $a, $b` 避免字串連接。
- 迴圈前快取最大值:`for ($i=0, $n=count($arr); $i<$n; $i++)`。
- 及時 `unset` 大變數釋放記憶體。
- 避免 `__get`、`__set`、`__autoload` 等魔術方法開銷。
- `require_once` 成本高,改用 Composer PSR-4 自動載入 (`classmap_authoritative`)。
- include/require 使用絕對路徑 `__DIR__ . '/file.php'`。
- 取得請求開始時間用 `$_SERVER['REQUEST_TIME']` 而非 `time()`。
- 字串操作優先 `strncasecmp`、`strpbrk`、`stripos` 替代正則。
- `strtr` > `str_replace` > `preg_replace` (單字元替換效能遞減 4 倍)。
11-20: 進階字串與流程控制
- 簡單替換考慮展開為多行單字元替換,避免陣列建構開銷。
- `switch-case` 優於多重 `if-elseif`。
- 禁用 `@` 錯誤抑制,極度低效。
- 啟用 Apache `mod_deflate` 壓縮傳輸。
- 資料庫連線用完即關閉,避免長連線洩漏。
- `$row['id']` 比 `$row[id]` 快 7 倍 (引號鍵名)。
- 錯誤訊息產生成本高,生產環境關閉顯示、僅記錄日誌。
- 迴圈內避免函數呼叫:`for ($i=0; $i
- 方法內局部變數遞增最快,接近函數呼叫速度。
- 全域變數遞增慢 2 倍於局部變數。
21-30: 物件導向與記憶體管理
- 物件屬性遞增 (`$this->prop++`) 慢 3 倍於局部變數。
- 未初始化變數遞增慢 9-10 倍,先宣告 `$x = 0`。
- 宣告未使用的區域變數也會降低速度 (PHP 檢查全域同名)。
- 方法呼叫速度與類別方法數量無關。
- 子類別方法執行快於父類別同名方法 (查找鏈較短)。
- 空函數呼叫 (1 參數) ≈ 7-8 次局部遞增;方法呼叫 ≈ 15 次。
- 單引號字串比雙引號快 (不掃描變數)。
- echo 多字串用逗號分隔最快。
- Apache 解析 PHP 比靜態 HTML 慢 2-10 倍,盡量靜態化。
- 啟用 OPcache (PHP 5.5+ 內建) 提升 25-100% 效能。
31-42: 快取、剖析與架構層面
- 字串長度檢查用 `isset($str[len])` 替代 `strlen()` (語言結構 vs 函數)。
- 前置遞增 `++$i` 比後置 `$i++` 快 (3 vs 4 opcodes)。
- 非必要不 OOP:物件/方法呼叫消耗大量記憶體。
- 資料結構優先用陣列,非必須類別封裝。
- 方法切分適度,YAGNI 原則。
- 隨時可重構,先解決問題。
- 盡量使用內建函數 (C 實作)。
- 極端瓶頸考慮 C 擴展 (FFI / Zephir / 原生 Extension)。
- 定期程式碼剖析:Xdebug Profiler、Blackfire、Tideways。
- 啟用 `mod_gzip`/`mod_deflate` 壓縮傳輸減少 80% 頻寬。
- 資料庫優化通常 ROI 最高:索引、EXPLAIN 分析、分頁優化、讀寫分離。
- 升級 PHP 版本:PHP 8.0 JIT、8.1 Fibers、8.2 隻讀屬性、8.3 新特性,每版提升 5-15%。
實務優化流程
- 建立基準:負載測試 (wrk, ab, k6) 記錄 QPS、延遲、記憶體
- 剖析熱點:Xdebug `profiler_enable=1` 生成 cachegrind 檔案
- 分析調用圖:KCacheGrind/QCacheGrind 找出耗時函數
- 針對性優化:修改代碼、加快取、調整 SQL、調整架構
- 驗證效果:相同負載測試比較指標
- 持續監控:APM (New Relic, Datadog, Elastic APM) 即時監控
常見誤區
- 微優化 (單引號/雙引號) 而忽略 SQL N+1 問題
- 未剖析就優化,導致代碼複雜化卻無效能提升
- 過度設計快取層,引入一致性、失效複雜度
- 忽略記憶體洩漏 (循環引用、大陣列未釋放)
- 生產環境開啟 Xdebug Profiler 導致嚴重效能下降