性能分析是 PHP 應用優化的基石。XHProf 是 Facebook 開源的分層性能分析器,支持函數級調用統計、CPU/內存/時間分佈、調用圖生成,比 Xdebug 更輕量、更適合生產環境採樣。本文涵蓋安裝配置、代碼埋點、Web UI 部署、結果解讀與持續集成方案。
hrtime | 手動埋點 | 極低 | ✅ | ❌ | 核心 |
# Ubuntu/Debian
apt-get install php-pear php-dev
pecl install xhprof
# CentOS/RHEL
yum install php-pear php-devel
pecl install xhprof
# Alpine
apk add php82-pear php82-dev
pecl install xhprof
# 驗證
php -m | grep xhprof
# Dockerfile
FROM php:8.2-fpm
RUN pecl install xhprof \
&& docker-php-ext-enable xhprof
# 或使用預構建鏡像
# FROM php:8.2-fpm-xhprof (社區鏡像)
extension=xhprof.so
; 可選:輸出目錄權限
; xhprof.output_dir = /var/tmp/xhprof
# 下載 xhprof 源碼包含的 xhprof_html 目錄
wget https://github.com/longxinH/xhprof/archive/refs/heads/master.zip
unzip master.zip
cp -r xhprof-master/xhprof_html /var/www/xhprof
# Nginx 配置
server {
listen 80;
server_name xhprof.local;
root /var/www/xhprof;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# xhgui (MongoDB 存儲,豐富儀表板)
composer require perftools/xhgui
# 配置 config.php
return [
'save.handler' => 'mongodb',
'db.host' => 'localhost',
'db.port' => 27017,
'db.name' => 'xhprof',
'profiler.enable' => true,
'profiler.simple_url' => 'profiler=1',
];
# 導入數據
php xhgui/import.php -f /path/to/xhprof_data
<?php
// bootstrap/profiler.php
class Profiler
{
private array $config;
private array $data = [];
public function __construct(array $config = [])
{
$this->config = array_merge([
'flags' => XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY,
'options' => [],
], $config);
if (!extension_loaded('xhprof')) {
throw new RuntimeException('XHProf extension not loaded');
}
}
public function enable(): void
{
xhprof_enable($this->config['flags'], $this->config['options']);
}
public function disable(): array
{
$this->data = xhprof_disable();
return $this->data;
}
public function save(string $namespace = 'app'): string
{
$this->disable();
// 需包含 xhprof_lib (來自源碼包)
require_once __DIR__ . '/xhprof_lib/utils/xhprof_lib.php';
require_once __DIR__ . '/xhprof_lib/utils/xhprof_runs.php';
$runs = new XHProfRuns_Default();
$runId = $runs->save_run($this->data, $namespace);
return $runId;
}
public function getReportUrl(string $runId, string $namespace = 'app'): string
{
return "https://xhprof.local/index.php?run=$runId&source=$namespace";
}
}
// 使用:分析特定業務邏輯
$profiler = new Profiler();
$profiler->enable();
// 核心業務代碼
$result = $orderService->createOrder($orderData);
$runId = $profiler->save('order_create');
echo "分析報告: " . $profiler->getReportUrl($runId);
<?php
// middleware/ProfilerMiddleware.php
class ProfilerMiddleware
{
public function handle(Request $request, Closure $next)
{
// 1% 採樣率,生產環境安全
if (mt_rand(1, 100) !== 1) {
return $next($request);
}
if (!extension_loaded('xhprof')) {
return $next($request);
}
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
$response = $next($request);
$data = xhprof_disable();
// 異步保存 (不阻塞響應)
$this->asyncSave($data, $request->path());
return $response;
}
private function asyncSave(array $data, string $path): void
{
// 推送到隊列/Redis/文件
$payload = json_encode([
'data' => $data,
'path' => $path,
'time' => microtime(true),
]);
// Redis LPUSH xhprof_queue $payload
// 或 file_put_contents("/tmp/xhprof_{$path}_{$time}.json", $payload, FILE_APPEND);
}
}
<?php
// analyze_job.php
#!/usr/bin/env php
<?php
require 'vendor/autoload.php';
$profiler = new Profiler(['flags' => XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY + XHPROF_FLAGS_NO_BUILTINS]);
$profiler->enable();
// 執行耗時任務
$worker->processBatch(1000);
$runId = $profiler->save('queue_worker');
echo "Run ID: $runId\n";
echo "Report: " . $profiler->getReportUrl($runId) . "\n";
ct | 調用次數 | 高頻調用 = 優化優先級 |
| wt | 墻鐘時間 (微秒) | **總耗時**,含 I/O 等待 |
| cpu | CPU 時間 | 計算密集型熱點 |
| mu | 內存使用 (字節) | 內存峰值、洩漏 |
| pmu | 峰值內存 | 內存尖峰 |
# 1. 數據庫查詢過多 (N+1) PDO->query() ct: 100 wt: 2.5s → 批量查詢/關聯預載入 # 2. 重複計算 MyClass::compute() ct: 5000 wt: 1.2s → 緩存/靜態變量/遞歸優化 # 3. 外部 API 調用 Guzzle->request() ct: 20 wt: 8.0s → 異步/並發/超時控制/熔斷 # 4. 大數組操作 array_merge() ct: 100 mu: 500MB → 生成器/分塊/引用傳遞 # 5. 自動加載 Composer\Autoload ct: 2000 wt: 0.5s → 優化自動加載/opcache
<?php
// 僅 0.1%-1% 請求啟用,避免性能影響
$sampleRate = 0.001; // 0.1%
if (mt_rand() / MT_RAND_MAX > $sampleRate) {
return; // 不啟用
}
# cron 每天清理 7 天前數據
find /var/tmp/xhprof -name "*.xhprof" -mtime +7 -delete
# 或 xhgui 內置清理
php xhgui/cleanup.php --days=7
<?php
// 保存前過濾 SQL 參數、密鑰、用戶數據
function sanitizeXhprofData(array $data): array
{
foreach ($data as $key => &$val) {
if (is_array($val)) {
$val = sanitizeXhprofData($val);
}
// 過濾函數名中的敏感信息 (如 SQL 查詢)
if (str_contains($key, 'PDO::query') || str_contains($key, 'password')) {
unset($data[$key]);
}
}
return $data;
}
# .github/workflows/performance.yml
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run benchmark
run: |
php benchmark.php > current.txt
- name: Compare with baseline
run: |
php compare.php baseline.txt current.txt --threshold=10%
# 關鍵函數耗時增長 >10% 失敗
Call to undefined function xhprof_enable() | 擴展未加載 | 檢查 php -m、php.ini、重啟 PHP-FPM |
| 圖形化界面空白/報錯 | Graphviz 未安裝 / 路徑錯誤 | apt-get install graphviz、配置 dot 路徑 |
| 內存洩漏導致進程 OOM | 長時間運行未 disable | 必須配對 enable/disable、使用 register_shutdown_function 保底 |
| 多進程衝突 (FPM) | 文件寫入衝突 | 使用 xhgui MongoDB 存儲、或進程隔離目錄 |
| 時間統計異常 | 系統時鐘調整 / 容器時區 | 使用 CPU 時間指標、容器同步時間 |
pecl install xhprof + extension=xhprof.sowt (總耗時)、cpu (計算熱點)、mu/pmu (內存)、ct (調用頻次)XHProf 以「輕量、採樣、圖形化」三大優勢,成為 PHP 生產環境性能分析的標準工具。建立「開發階段全量分析 → 測試階段壓測分析 → 生產階段採樣巡檢」三級分析體系,讓性能優化從「拍腦袋」變為「數據驅動」。