在效能優化、基準測試、演算法比較等場景中,精準測量函數執行時間是核心需求。PHP 提供 microtime() 與 hrtime()(PHP 7.3+)兩種高精度計時器,本文封裝一個可複用的 EfficiencyTester 類,支援多次執行平均值、不同時間單位與自訂測試次數。
<?php
class EfficiencyTester {
private int $testTimes = 1000;
private string $timeModel = 'hrtime'; // 'hrtime' | 'microtime' | 'time'
public function __construct(int $testTimes = 1000, string $timeModel = 'hrtime') {
$this->testTimes = max(1, $testTimes);
$this->timeModel = $timeModel;
}
/** 取得高精度時間戳(奈秒/微秒/秒) */
private function getTime(): float {
switch ($this->timeModel) {
case 'hrtime':
// 回傳奈秒,轉為秒單位浮點數
return hrtime(true) * 1e-9;
case 'microtime':
return microtime(true);
case 'time':
return time();
default:
return hrtime(true) * 1e-9;
}
}
/** 單次執行測量 */
public function testOnce(callable $callable): float {
$start = $this->getTime();
$callable();
$end = $this->getTime();
return $end - $start;
}
/** 多次執行取平均值 */
public function test(callable $callable): float {
$total = 0.0;
for ($i = 0; $i < $this->testTimes; $i++) {
$total += $this->testOnce($callable);
}
return $total / $this->testTimes;
}
/** 取得統計摘要(最小/最大/平均/中位數) */
public function testWithStats(callable $callable): array {
$times = [];
for ($i = 0; $i < $this->testTimes; $i++) {
$times[] = $this->testOnce($callable);
}
sort($times);
$count = count($times);
return [
'min' => $times[0],
'max' => $times[$count - 1],
'avg' => array_sum($times) / $count,
'median'=> $times[$count >> 1],
'samples' => $times,
];
}
}
?>
<?php
require_once 'EfficiencyTester.php';
$tester = new EfficiencyTester(10000, 'hrtime'); // 10000 次,奈秒精度
// 測試內建函數
$avg = $tester->test('rand');
echo "rand() 平均耗時: {$avg} 秒\n";
// 測試匿名函數
$stats = $tester->testWithStats(function() {
$arr = range(1, 100);
shuffle($arr);
});
printf("shuffle 統計: 平均 %.6fs, 中位數 %.6fs, 最小 %.6fs, 最大 %.6fs\n",
$stats['avg'], $stats['median'], $stats['min'], $stats['max']);
// 比較兩種字串連接方式
$concatAvg = $tester->test(fn() => implode('', range('a', 'z')));
$sprintfAvg = $tester->test(fn() => sprintf('%s%s', 'a', 'b'));
echo "implode vs sprintf: {$concatAvg} vs {$sprintfAvg}\n";
?>
| 函式 | 精度 | 單調性 | PHP 版本 | 適用場景 |
|---|---|---|---|---|
hrtime(true) | 奈秒 (1e-9s) | 單調遞增 | 7.3+ | 高精度基準測試、分佈式追蹤 |
microtime(true) | 微秒 (1e-6s) | 非單調(受 NTP 調整) | 所有 | 相容舊版、一般效能分析 |
time() | 秒 | 非單調 | 所有 | 粗略計時、超時判斷 |
建議:PHP 7.3+ 環境優先使用 hrtime(),避免系統時間同步導致負數耗時。
<?php
// 預熱:讓 JIT/OpCache/CPU 預熱
for ($i = 0; $i < 100; $i++) $callable();
// 隔離測試:關閉 GC、固定 CPU 親和性(需權限)
gc_disable();
// 測試...
gc_enable();
?>
配合 memory_get_peak_usage(true) 與 getrusage() 可獲得全維度資源消耗:
<?php
function profile(callable $fn): array {
gc_collect_cycles();
$memBefore = memory_get_usage(true);
$cpuBefore = getrusage();
$fn();
$memAfter = memory_get_peak_usage(true);
$cpuAfter = getrusage();
return [
'memory_bytes' => $memAfter - $memBefore,
'user_cpu_sec' => ($cpuAfter['ru_utime.tv_sec'] + $cpuAfter['ru_utime.tv_usec'] / 1e6)
- ($cpuBefore['ru_utime.tv_sec'] + $cpuBefore['ru_utime.tv_usec'] / 1e6),
'sys_cpu_sec' => ($cpuAfter['ru_stime.tv_sec'] + $cpuAfter['ru_stime.tv_usec'] / 1e6)
- ($cpuBefore['ru_stime.tv_sec'] + $cpuBefore['ru_stime.tv_usec'] / 1e6),
];
}
?>
對於生產級效能分析,建議使用專業工具:
本文提供的 EfficiencyTester 適合單元測試階段、CI 管線中的微基準測試、以及快速驗證優化成果。掌握精準計時技術,讓效能優化有據可依。