在PHP 性能調優的過程中,準確測量腳本的執行時間和資源消耗是非常重要的。常見的做法是結合microtime()和getrusage()兩個函數來監控腳本運行時間和系統資源使用情況。然而,這種方法真的可靠嗎?本文將詳細探討這兩者的使用方式及其準確性。
microtime()返回當前Unix 時間戳的微秒數部分,常用於高精度計時。典型用法是先在腳本開始時調用一次,結束時再調用一次,兩者相減即可得到腳本執行的時間。
<?php
$start = microtime(true);
// 模擬耗時操作
usleep(500000); // 500毫秒
$end = microtime(true);
$elapsed = $end - $start;
echo "腳本執行時間: {$elapsed} 秒\n";
?>
這種方式的優點是簡單直接,且精度足夠衡量大部分PHP 腳本性能。
getrusage()返回當前進程資源使用情況的數組,包括用戶CPU時間、系統CPU時間、內存使用情況等。常用於更細粒度的性能分析。
<?php
$usage_start = getrusage();
// 模擬耗時操作
usleep(500000);
$usage_end = getrusage();
$user_cpu_start = $usage_start["ru_utime.tv_sec"] + $usage_start["ru_utime.tv_usec"] / 1e6;
$user_cpu_end = $usage_end["ru_utime.tv_sec"] + $usage_end["ru_utime.tv_usec"] / 1e6;
$user_cpu_time = $user_cpu_end - $user_cpu_start;
echo "用戶態CPU時間: {$user_cpu_time} 秒\n";
?>
通過計算用戶態CPU時間差,我們可以知道CPU 實際處理腳本所用的時間,而非包括等待時間的整體運行時長。
有人會同時使用這兩者來判斷腳本性能:
用microtime()計算總耗時(wall-clock time)
用getrusage()計算CPU時間(用戶態+系統態)
示例代碼:
<?php
$start_time = microtime(true);
$start_usage = getrusage();
// 模擬耗時操作
usleep(500000);
$end_time = microtime(true);
$end_usage = getrusage();
$elapsed_time = $end_time - $start_time;
$user_cpu_start = $start_usage["ru_utime.tv_sec"] + $start_usage["ru_utime.tv_usec"] / 1e6;
$user_cpu_end = $end_usage["ru_utime.tv_sec"] + $end_usage["ru_utime.tv_usec"] / 1e6;
$user_cpu_time = $user_cpu_end - $user_cpu_start;
$system_cpu_start = $start_usage["ru_stime.tv_sec"] + $start_usage["ru_stime.tv_usec"] / 1e6;
$system_cpu_end = $end_usage["ru_stime.tv_sec"] + $end_usage["ru_stime.tv_usec"] / 1e6;
$system_cpu_time = $system_cpu_end - $system_cpu_start;
echo "總耗時: {$elapsed_time} 秒\n";
echo "用戶CPU時間: {$user_cpu_time} 秒\n";
echo "系統CPU時間: {$system_cpu_time} 秒\n";
?>
microtime()可測量真實時間跨度,包含所有等待和阻塞時間。
getrusage()反映CPU實際處理時間,能剔除等待I/O等時間,更真實地體現腳本對CPU資源的佔用。
兩者結合,可以較全面地了解腳本執行效率及系統負載。
getrusage()並非所有操作系統都支持,Windows 系統上的PHP 就沒有完整支持此函數。
getrusage()只測量當前進程資源,無法涵蓋外部調用或子進程的資源消耗。
腳本中含有大量I/O等待或網絡請求時,CPU時間與真實耗時差距較大, getrusage()反映不出I/O瓶頸。
microtime()受系統時鐘精度影響,極短時間的測量可能不准確。
對於CPU 密集型的PHP 腳本,結合兩者測量能提供較準確的性能信息。
對於I/O 密集型腳本,單用getrusage()不足以反映整體性能, microtime()更重要。
建議結合其他性能工具(如Xdebug、Blackfire 等)進行綜合分析。
使用getrusage()時注意兼容性問題,特別是在跨平台環境下。
getrusage()和microtime()各有千秋,結合使用確實能更細緻地評估PHP 腳本性能。但是否靠譜,取決於具體使用場景、腳本性質以及測試環境。它們是性能分析的基礎工具,而非萬能的銀彈。只有結合業務特點和更多性能指標,才能科學地判斷和優化腳本性能。