getrusage()是一個PHP 原生函數,用於獲取當前進程或其子進程的資源使用情況。它返回一個數組,包含了多個系統層面的數據,例如用戶態/內核態CPU 時間、內存頁故障次數、上下文切換次數等。
$usage = getrusage();
常用的幾個字段包括:
ru_utime.tv_sec與ru_utime.tv_usec :用戶態消耗的時間(秒和微秒)
ru_stime.tv_sec與ru_stime.tv_usec :系統態消耗的時間(秒和微秒)
ru_minflt :無需從磁盤調入的頁錯誤數量(軟缺頁)
ru_majflt :從磁盤調入的頁錯誤數量(硬缺頁)
ru_nvcsw和ru_nivcsw :自願和非自願上下文切換次數
要監控數據庫查詢對系統的影響,最直接的方式是:
在查詢前記錄一次getrusage() ;
執行查詢;
查詢後再次記錄一次getrusage() ;
對比兩次記錄的差值。
示例代碼如下:
function getResourceUsageDiff($start, $end) {
$diff = [];
foreach ($end as $key => $value) {
if (isset($start[$key])) {
$diff[$key] = $value - $start[$key];
}
}
return $diff;
}
$before = getrusage();
// 模擬數據庫查詢
$mysqli = new mysqli("localhost", "user", "password", "database");
$result = $mysqli->query("SELECT * FROM users WHERE email LIKE '%@example.com'");
$after = getrusage();
$usageDiff = getResourceUsageDiff($before, $after);
echo "<pre>";
print_r($usageDiff);
echo "
";
此代碼可以輸出查詢所產生的系統資源變化。例如,如果你看到ru_stime.tv_usec明顯上升,則說明該查詢引起了系統態CPU 的增加,可能存在大量I/O 操作。
為了更實用,可以將測量過程封裝成一個函數,支持自動記錄查詢語句和資源變化:
function profileQuery($query, $mysqli) {
$before = getrusage();
$result = $mysqli->query($query);
$after = getrusage();
$usageDiff = getResourceUsageDiff($before, $after);
file_put_contents("/var/log/db_profile.log", json_encode([
'query' => $query,
'usage' => $usageDiff,
'time' => date('c')
]) . PHP_EOL, FILE_APPEND);
return $result;
}
這種方式可以讓你在不打擾正常邏輯的同時,持續收集查詢對系統資源的影響,從而為後續優化提供依據。
對比不同索引結構的影響
使用相同條件、不同索引結構的查詢,比較系統資源佔用,可以直觀評估索引調整是否有效
監控批量查詢或大數據分頁性能
當面對分頁或批量查詢時,觀察ru_majfl t 、 ru_nvcsw是否增長,可以判斷查詢是否觸發了大量內存調頁或上下文切換
在壓力測試中對比資源使用
配合Apache Benchmark、JMeter 等工具進行並發測試,記錄資源佔用變化,分析系統在高負載下的表現
如果你希望調試時在瀏覽器中更清晰地查看getrusage()的變化,可以使用如下代碼格式化輸出:
function formatUsage(array $usage) {
return sprintf(
"User CPU: %.4fs, System CPU: %.4fs, Major Faults: %d, Voluntary CS: %d",
$usage['ru_utime.tv_sec'] + $usage['ru_utime.tv_usec'] / 1e6,
$usage['ru_stime.tv_sec'] + $usage['ru_stime.tv_usec'] / 1e6,
$usage['ru_majflt'] ?? 0,
$usage['ru_nvcsw'] ?? 0
);
}
echo formatUsage($usageDiff);