PHP 性能優化是系統架構演進的永恆主題。本文結合 strace 系統調用分析、APC/Opcode 快取、realpath_cache、Smarty 模板優化、編碼層面 50+ 微優化技巧,構建完整的 PHP 效能調優知識體系。
# 1. 單進程除錯模式啟動 apache2ctl -X & # 2. 找到 PID ps -ef | grep httpd # 3. 追蹤系統調用 strace -p $PID -o /tmp/strace.log # 發送 HTTP 請求,分析日誌
現象: 大量 stat64("/error/dir/test.php") = -1 ENOENT。
解決:
include_path 中的 . 相對路徑,高頻目錄前置。include/require。錯誤寫法:RewriteRule .* /index.php 會觸發 stat64("/index.php") 失敗。
正確寫法:RewriteRule .* %{DOCUMENT_ROOT}%/index.php 使用絕對路徑。
若 LogFormat 包含 %t(時間),每次請求會 stat64("/etc/localtime")。
方案:前端掛 Nginx/Haproxy 記錄存取日誌,Apache 關閉 access_log。
PHP 5.2 對 /a/b/c/d.php 需逐層 lstat64。
方案:
include_once/require_once(會觸發 realpath 檢查符號連結)。realpath_cache_size=256k, realpath_cache_ttl=3600。pecl install apc 或編譯 --enable-apc --enable-apc-mmap。apc.stat=0(停止檢查檔案修改時間),部署時呼叫 apc_clear_cache()。$smarty->compile_check = false; 關閉編譯檢查,部署時清空 compile_dir。$smarty->caching = true; 頁面級快取。| 參數 | 建議值 | 說明 |
|---|---|---|
| apc.enabled | On | 啟用 APC |
| apc.shm_size | 128M~256M | 共享記憶體大小 |
| apc.num_files_hint | 1024~4096 | 預估檔案數 |
| apc.ttl / apc.user_ttl | 7200~36000 | 快取存活秒數,0 表永不超時(不建議) |
| apc.gc_ttl | 3600 | 垃圾回收表存活秒數 |
| apc.stat | Off | 生產環境關閉檢查,部署時手動清除 |
| apc.write_lock | On | 防併發衝突 |
| apc.max_file_size | 1M | 單檔快取上限 |
| # | 技巧 | 效能差異 |
|---|---|---|
| 1 | 單引號替代雙引號字串 | 避免變數解析,echo 多參數用逗號 |
| 2 | 方法能 static 就 static | 速度提升 ~4 倍 |
| 3 | $row['id'] 比 $row[id] 快 7 倍 | 避免常數查找 |
| 4 | echo $a,$b 比 echo $a.$b 快 | 避免字串連接分配記憶體 |
| 5 | for 循環前確定最大值,或用 foreach | 避免重複計算 count() |
| 6 | 及時 unset 大陣列/物件釋放記憶體 | 降低 memory_get_usage() |
| 7 | 避免 __get/__set/__autoload 魔術方法 | 額外呼叫開銷 |
| 8 | 慎用 require_once | realpath 檢查開銷大 |
| 9 | include 使用絕對路徑 | 省去 include_path 遍歷 |
| 10 | 用 $_SERVER['REQUEST_TIME'] 替代 time() | 避免函數呼叫 |
| 11 | strtr > str_replace > preg_replace | strtr 效率是 str_replace 4 倍 |
| 12 | 字串替換參數為字元優於陣列 | 減少內部遍歷 |
| 13 | switch 優於多重 if/else | 跳躍表優化 |
| 14 | 避免 @ 抑制錯誤 | 極度低效 |
| 15 | 開啟 Apache mod_deflate 壓縮輸出 | 傳輸量降 80% |
| 16 | 資料庫連線用完即關,避免長連線 | 釋放連線池 |
| 17 | 錯誤訊息產生開銷大 | 生產環境關閉 display_errors |
| 18 | 區域變數遞增最快 | 幾乎等同函數內區域變數 |
| 19 | 全域變數遞增比區域慢 2 倍 | 符號表查找 |
| 20 | 物件屬性 $this->prop++ 慢 3 倍 | 物件屬性存取開銷 |
| 21 | 未預定義區域變數遞增慢 9-10 倍 | 需初始化符號表項 |
| 22 | 定義但未使用區域變數也減慢速度 | PHP 掃描全域變數 |
| 23 | 方法數量不影響呼叫效能 | 測試證實 |
| 24 | 子類方法執行快於父類同名方法 | 繼承鏈查找 |
| 25 | 空函數呼叫 ≈ 7-8 次區域變數遞增 | 函數呼叫開銷基準 |
| 26 | PHP 解析比靜態 HTML 慢 2-10 倍 | 多用靜態頁/CDN |
| 27 | 引入 Opcode 快取提升 25-100% | APC/OPcache 必裝 |
| 28 | 使用 memcached 快取運算碼/資料 | 減輕 DB 壓力 |
| 29 | isset($str{5}) 比 strlen($str)<5 快 | 語言結構 vs 函數呼叫 |
| 30 | ++$i 比 $i++ 快 | 少一條 opcode,無臨時變數 |
(篇幅限制僅列前 30 條,完整 50+ 條見原文)
PHP 性能優化是系統工程:從 strace 找瓶頸、調 php.ini 核心參數、裝 Opcode 快取、優化模板引擎、落實編碼微優化。建議優先順序:升級 PHP 版本 > 開啟 OPcache > 調整 realpath_cache > 靜態化熱點頁 > 程式碼微優化。工欲善其事,必先利其器——善用 Xdebug Profiler、Blackfire 定位真正瓶頸,避免過早優化。