隨著專案迭代,PHP 應用常面臨響應變慢、資源耗盡等問題。本文從三個維度提供實戰優化方案:程式碼級性能剖析、外部介面並發優化、Opcode 緩存加速。
# 假設 PHP 安裝於 /home/ad/php
cd /home/ad
wget https://xdebug.org/files/xdebug-2.1.0.tgz
tar -zxvf xdebug-2.1.0.tgz
cd xdebug-2.1.0
/home/ad/php/bin/phpize
./configure --enable-xdebug --with-php-config=/home/ad/php/bin/php-config
make && make install
安裝完成後,將擴展路徑加入 php.ini:
[xdebug]
zend_extension = "/home/ad/php/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so"
xdebug.auto_trace = on
xdebug.auto_profile = on
xdebug.collect_params = on
xdebug.collect_return = on
xdebug.profiler_enable = on
xdebug.trace_output_dir = "/home/ad/xdebug_log"
xdebug.profiler_output_dir = "/home/ad/xdebug_log"
重啟 Apache,訪問任意頁面,/home/ad/xdebug_log 將生成 cachegrind.out.* 分析文件。
| 參數 | 作用 |
|---|---|
| xdebug.auto_trace | 自動記錄所有函數調用流程 |
| xdebug.auto_profile | 自動啟用性能分析器 |
| xdebug.collect_params | 記錄函數調用時的參數值 |
| xdebug.collect_return | 記錄函數返回值 |
| xdebug.trace_output_dir | 函數追蹤日誌輸出目錄 |
| xdebug.profiler_output_dir | 性能分析數據輸出目錄 |
<?php
function a() { echo "aaa"; }
function b() {
a(); sleep(1);
a(); sleep(1);
a();
}
b();
?>
使用 WinCacheGrind (下載) 打開生成的 cachegrind.out.*,即可直觀查看:
快速定位「誰調用了多少次」、「哪裡消耗最久」。
傳統 foreach + curl_exec 串行請求 3 個介面,每個 500ms,總耗時 1.5s+。
function curl_fetch($url, $timeout=3) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_RETURNTRANSFER => 1,
]);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$urls = ['taobao'=>'https://www.taobao.com', 'sohu'=>'https://www.sohu.com', 'sina'=>'https://www.sina.com.cn'];
$start = microtime(true);
foreach ($urls as $k=>$v) $data[$k] = curl_fetch($v);
echo "耗時: " . (microtime(true)-$start); // 約 0.614 秒 (網絡較快時)
function curl_multi_fetch($urls) {
$mh = curl_multi_init();
$ch = [];
foreach ($urls as $k=>$v) {
$ch[$k] = curl_init();
curl_setopt_array($ch[$k], [
CURLOPT_URL => $v,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 2,
]);
curl_multi_add_handle($mh, $ch[$k]);
}
$running = null;
do { curl_multi_exec($mh, $running); } while ($running > 0);
$result = [];
foreach ($ch as $k=>$c) {
$result[$k] = curl_multi_getcontent($c);
curl_multi_remove_handle($mh, $c);
curl_close($c);
}
curl_multi_close($mh);
return $result;
}
$start = microtime(true);
$data = curl_multi_fetch($urls);
echo "耗時: " . (microtime(true)-$start); // 約 0.316 秒,耗時減半!
curl_multi_init() 創建批處理句柄curl_multi_add_handle() 加入多個單獨請求curl_multi_exec() 非阻塞執行curl_multi_select() 等待網絡活動 (可選,提高 CPU 效率)curl_multi_getcontent() 獲取各請求結果
PHP 腳本執行經歷:詞法分析 → 語法分析 → 編譯為 Opcode → Zend VM 執行 Opcode。
Opcode 緩存將編譯產生的中間碼存入共享內存,下次請求直接跳過前三步,極大提升吞吐量。
wget https://pecl.php.net/get/APC-3.1.6.tgz
tar -zxvf APC-3.1.6.tgz
cd APC-3.1.6
/home/ad/php/bin/phpize
./configure --enable-apc --enable-apc-mmap --with-php-config=/home/ad/php/bin/php-config
make && make install
[apc]
extension = apc.so
apc.enabled = 1
apc.shm_segments = 1
apc.shm_size = 128M
apc.ttl = 7200
apc.user_ttl = 7200
apc.num_files_hint = 10000
apc.stat = 0
apc.max_file_size = 2M
apc.write_lock = 1
apc.cache_by_default = 1
| 參數 | 推薦值 | 說明 |
|---|---|---|
| apc.shm_size | 128M~256M | 共享內存大小,視項目文件數量與體積調整 |
| apc.stat | 0 (生產) / 1 (開發) | 0 時不檢查文件修改,性能最佳;修改代碼後需重啟 Apache 或呼叫 apc_clear_cache() |
| apc.ttl | 7200~36000 | 緩存條目存活秒數,0 為永不過期(易導致內存滿無法寫入新條目) |
| apc.write_lock | 1 | 高併發下防止多進程同時寫入同一檔案造成競爭 |
| apc.max_file_size | 1M~5M | 超過此大小的文件不緩存,避免大文件佔滿共享內存 |
| apc.filters | 視情況 | 配合 apc.cache_by_default 實現白/黑名單緩存策略 |
下載 APC 源碼包中的 apc.php 部署到 Web 目錄,即可查看:
三者結合,可將典型 PHP 應用吞吐量提升 3-10 倍,響應時間降低 50% 以上。