效能調優的第一步是測量。PHP 提供 microtime(true) 取得微秒時間戳,配合 memory_get_usage() 即可輕鬆建立效能分析工具。本文提供可直接使用的 Runtime 類、格式化輸出函式,並示範如何找出效能瓶頸。
<?php
class Runtime {
private $startTime = 0;
private $endTime = 0;
private $startMem = 0;
private $endMem = 0;
public function start() {
$this->startTime = microtime(true);
$this->startMem = memory_get_usage(true); // 含 PHP 分配的記憶體
}
public function stop() {
$this->endTime = microtime(true);
$this->endMem = memory_get_usage(true);
}
public function elapsedMs() {
return round(($this->endTime - $this->startTime) * 1000, 2);
}
public function memoryDiff($format = true) {
$diff = $this->endMem - $this->startMem;
return $format ? self::formatBytes($diff) : $diff;
}
public function peakMemory($format = true) {
$peak = memory_get_peak_usage(true);
return $format ? self::formatBytes($peak) : $peak;
}
public static function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$value = $bytes / (1024 ** $pow);
return round($value, $precision) . ' ' . $units[$pow];
}
public function report() {
return sprintf(
"⏱ 耗時: %s | 📊 記憶體增量: %s | 📈 峰值: %s",
$this->elapsedMs() . ' ms',
$this->memoryDiff(),
$this->peakMemory()
);
}
}
<?php
require 'Runtime.php';
$rt = new Runtime();
$rt->start();
// ---- 待測程式碼區塊 ----
$sum = 0;
for ($i = 0; $i < 1_000_000; $i++) {
$sum += $i;
}
$arr = range(1, 10000); // 配置記憶體
// ------------------------
$rt->stop();
echo $rt->report();
// 輸出範例:⏱ 耗時: 45.23 ms | 📊 記憶體增量: 384 KB | 📈 峰值: 2.12 MB
$rt = new Runtime();
$rt->start();
// 區段 1: DB 查詢
$t1 = microtime(true);
$users = $db->query("SELECT * FROM users LIMIT 1000");
$rt->lap('DB查詢', $t1);
// 區段 2: 資料處理
$t2 = microtime(true);
$processed = array_map(function($u) { return strtoupper($u['name']); }, $users);
$rt->lap('資料處理', $t2);
// 區段 3: 視圖渲染
$t3 = microtime(true);
echo $tpl->render($processed);
$rt->lap('視圖渲染', $t3);
$rt->stop();
$rt->printLaps();
擴充 Runtime 加入 laps 陣列與 lap($label, $startTime) 方法即可實現。
| 現象 | 可能原因 | 驗證方式 |
|---|---|---|
| 耗時高、記憶體正常 | 演算法複雜度高、外部 API 慢、DB 無索引 | 區段計時 + EXPLAIN SQL |
| 記憶體增量大 | 一次載入大量資料、未釋放大變數、迴圈字串連接 | memory_get_usage 觀察曲線 |
| 峰值遠大於增量 | 中間產生巨大暫時變數(如大陣列拷貝) | 分區段監控峰值 |
| 首次請求慢、後續快 | OpCache 未暖機、自動載入掃描、資料庫連線建立 | 對比第 1 次 vs 第 N 次 |
xhprof / tideways / Blackfire 做深度剖析。xdebug 在正式機(極大影響效能)。