定位效能瓶頸需要精準測量各程式區塊耗時。`microtime()` 提供微秒級時間戳,配合簡易封裝即可實現分段計時、多點記錄、自動匯總。
<?php
function timer($mode = 0) {
static $start;
if ($mode === 0) { // 啟動/重置
$start = microtime(true);
return;
}
$now = microtime(true);
$elapsed = ($now - $start) * 1000; // 毫秒
if ($mode === 1) { // 記錄分段並繼續
echo "段耗時: " . sprintf("%.3f ms", $elapsed) . "
";
$start = $now; // 重置起點為當前,供下一段
} elseif ($mode === 2) { // 結束總計
echo "總耗時: " . sprintf("%.3f ms", $elapsed) . "
";
}
}
// 使用
timer(); // 開始
// ... 程式碼區塊 A ...
timer(1); // 區塊 A 耗時、重置
// ... 程式碼區塊 B ...
timer(1); // 區塊 B 耗時、重置
// ... 程式碼區塊 C ...
timer(2); // 總耗時 (從最開始)
?>
echo microtime(true); // 1712345678.123456 echo microtime(); // "0.123456 1712345678" (字串,舊版相容)
**永遠用 `microtime(true)`** 直接運算,避免字串解析開銷與精度損失。
<?php
class Profiler {
private $marks = [];
private $start;
public function __construct() { $this->start = microtime(true); }
public function mark(string $label): void {
$this->marks[$label] = microtime(true);
}
public function report(): array {
$end = microtime(true);
$report = [];
$prev = $this->start;
foreach ($this->marks as $label => $time) {
$report[$label] = ($time - $prev) * 1000;
$prev = $time;
}
$report['_total'] = ($end - $this->start) * 1000;
return $report;
}
}
// 使用
$p = new Profiler();
// DB 查詢
$p->mark('db_query');
// 模板渲染
$p->mark('render');
// 發送郵件
$p->mark('send_mail');
print_r($p->report());
/*
Array (
[db_query] => 12.345
[render] => 45.678
[send_mail] => 234.567
[_total] => 292.590
)
*/
?>
從 `microtime` 手動埋點到專業分析工具,建立「可觀測、可量化、可優化」的效能工程文化。