首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 性能分析利器:G() 函數實現微秒級計時與內存統計

     編輯:PHP 相關知識

ThinkPHP 經典的 G() 函數以極簡 API 實現「標記開始/結束 → 統計耗時/內存」,是輕量級性能剖析的首選工具。本文深度解析其原理,提供增強版實現(支持多段計時、內存單位自動換算、PHP 8+ 類型提示),並示範實戰用法。

原版核心邏輯

function G($start, $end = '', $dec = 4) {
    static $_info = [];
    static $_mem  = [];

    if (is_float($end)) {
        // 記錄時間戳(微秒)
        $_info[$start] = $end;
    } elseif (!empty($end)) {
        // 統計區間
        if (!isset($_info[$end])) $_info[$end] = microtime(true);
        if (defined('MEMORY_LIMIT_ON') && MEMORY_LIMIT_ON && $dec === 'm') {
            if (!isset($_mem[$end])) $_mem[$end] = memory_get_usage();
            return number_format(($_mem[$end] - $_mem[$start]) / 1024); // KB
        } else {
            return number_format($_info[$end] - $_info[$start], $dec); // 秒,保留 $dec 位小數
        }
    } else {
        // 標記開始
        $_info[$start] = microtime(true);
        if (defined('MEMORY_LIMIT_ON') && MEMORY_LIMIT_ON) {
            $_mem[$start] = memory_get_usage();
        }
    }
}

增強版:GTimer 類(更現代、更強大)

<?php
declare(strict_types=1);

/**
 * 輕量級性能分析器
 * 用法:
 * GTimer::mark('start');
 * // ... code ...
 * GTimer::mark('end');
 * echo GTimer::elapsed('start', 'end', 6); // 秒,6 位小數
 * echo GTimer::memory('start', 'end'); // KB
 */
class GTimer {
    private static array $time = [];
    private static array $mem  = [];

    /** 標記時間點(自動記錄內存) */
    public static function mark(string $name): void {
        self::$time[$name] = microtime(true);
        self::$mem[$name]  = memory_get_usage(true); // 真實分配內存
    }

    /** 獲取兩點間耗時(秒) */
    public static function elapsed(string $start, string $end = '', int $precision = 6): float {
        $end = $end ?: 'now';
        if ($end === 'now') self::mark('now');

        if (!isset(self::$time[$start]) || !isset(self::$time[$end])) {
            throw new InvalidArgumentException("標記 '$start' 或 '$end' 不存在");
        }
        return round(self::$time[$end] - self::$time[$start], $precision);
    }

    /** 獲取兩點間內存增長(自動單位:B/KB/MB/GB) */
    public static function memory(string $start, string $end = ''): string {
        $end = $end ?: 'now';
        if ($end === 'now') self::mark('now');

        $diff = self::$mem[$end] - self::$mem[$start];
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = 0;
        while (abs($diff) >= 1024 && $i < count($units) - 1) {
            $diff /= 1024;
            $i++;
        }
        return round($diff, 2) . ' ' . $units[$i];
    }

    /** 重置所有標記 */
    public static function reset(): void {
        self::$time = [];
        self::$mem  = [];
    }
}

實戰示例

<?php
require 'GTimer.php';

GTimer::mark('request_start');

// 模擬業務邏輯
$data = [];
for ($i = 0; $i < 100000; $i++) {
    $data[] = md5($i);
}
GTimer::mark('data_prepared');

// 數據庫查詢模擬
usleep(50000); // 50ms
GTimer::mark('db_done');

// 輸出報告
echo "總耗時: " . GTimer::elapsed('request_start', 'db_done') . " 秒\n";
echo "準備階段: " . GTimer::elapsed('request_start', 'data_prepared') . " 秒\n";
echo "DB 階段: " . GTimer::elapsed('data_prepared', 'db_done') . " 秒\n";
echo "內存增長: " . GTimer::memory('request_start', 'db_done') . "\n";

// 輸出示例:
// 總耗時: 0.123456 秒
// 準備階段: 0.073456 秒
// DB 階段: 0.050000 秒
// 內存增長: 8.45 MB

原版 vs 增強版對比

特性原版 G()GTimer 類
API 風格單函數多態靜態方法,語義清晰
多段計時支持(不同標記名)支持,更直觀
內存單位固定 KB自動換算 B/KB/MB/GB
類型安全無PHP 8+ 嚴格類型
錯誤處理靜默返回拋出異常
依賴常量MEMORY_LIMIT_ON無,直接用 memory_get_usage(true)

最佳實踐建議

  1. 入口標記:在框架入口(如 index.php)第一行調用 GTimer::mark('bootstrap')。
  2. 關鍵節點:路由解析完成、控制器實例化、數據庫查詢前後、視圖渲染前後打標記。
  3. 中間件收集:在響應發送前統一輸出性能報告到 Header(X-Request-Time、X-Memory-Usage)或日誌系統。
  4. 生產環境:關閉詳細統計或僅採樣 1% 請求,避免 microtime/memory_get_usage 開銷(雖極小但非零)。

總結

G() 函數以「靜態數組 + microtime + memory_get_usage」三板斧構建了極簡性能剖析器。理解其原理後,可根據項目需求輕鬆擴展為類版本、集成到中間件、對接 APM 系統(如 SkyWalking、Pinpoint),實現全鏈路可觀測。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved