Skip to content

HRTime 高精度计时

PHP 8.1 引入了 HRTime(High Resolution Time)扩展,提供了纳秒级的高精度时间测量功能。相比 microtime(true) 的微秒精度,HRTime 可以测量更小的时间间隔,特别适合性能分析和基准测试。

前置知识

阅读本节前,建议先了解:DateTime 类

基础概念

HRTime 的优势

函数精度说明
time()Unix 时间戳
microtime(true)微秒 (1e-6)浮点秒数
hrtime(true)纳秒 (1e-9)高精度整数

安装

HRTime 从 PHP 8.1 开始成为核心扩展,默认启用,无需额外安装。

hrtime() 函数

基本用法

php
<?php
declare(strict_types=1);

// hrtime() 返回纳秒级时间
$nanoseconds = hrtime(true);
echo "纳秒时间戳: {$nanoseconds}" . PHP_EOL;

// 转换为秒
$seconds = $nanoseconds / 1_000_000_000;
echo "秒: {$seconds}" . PHP_EOL;

// 转换为毫秒
$milliseconds = $nanoseconds / 1_000_000;
echo "毫秒: {$milliseconds}" . PHP_EOL;

// 返回数组形式 [秒, 纳秒]
$parts = hrtime(false);
echo "秒: {$parts[0]}, 纳秒: {$parts[1]}" . PHP_EOL;

性能测量

php
<?php
declare(strict_types=1);

/**
 * 使用 hrtime 测量代码执行时间
 */
function benchmark(callable $fn, int $iterations = 1000): array
{
    $totalNs = 0;
    $times = [];

    for ($i = 0; $i < $iterations; $i++) {
        $start = hrtime(true);
        $fn();
        $end = hrtime(true);

        $elapsed = $end - $start;
        $totalNs += $elapsed;
        $times[] = $elapsed;
    }

    sort($times);

    return [
        'total_ms'       => $totalNs / 1_000_000,
        'avg_ns'         => (int) ($totalNs / $iterations),
        'min_ns'         => $times[0],
        'max_ns'         => $times[count($times) - 1],
        'p50_ns'         => $times[(int) (count($times) * 0.50)],
        'p95_ns'         => $times[(int) (count($times) * 0.95)],
        'p99_ns'         => $times[(int) (count($times) * 0.99)],
        'iterations'     => $iterations,
    ];
}

// 测试 json_encode 性能
$data = array_fill(0, 1000, ['id' => 1, 'name' => '张三', 'active' => true]);
$result = benchmark(fn() => json_encode($data), 1000);

echo "json_encode 基准测试:" . PHP_EOL;
echo "总耗时: {$result['total_ms']} ms" . PHP_EOL;
echo "平均: {$result['avg_ns']} ns" . PHP_EOL;
echo "P50: {$result['p50_ns']} ns" . PHP_EOL;
echo "P95: {$result['p95_ns']} ns" . PHP_EOL;
echo "P99: {$result['p99_ns']} ns" . PHP_EOL;

与 microtime 对比

php
<?php
declare(strict_types=1);

// microtime(true) 精度有限
$before = microtime(true);
usleep(100); // 100 微秒
$after = microtime(true);
echo "microtime 差值: " . (($after - $before) * 1_000_000) . " us" . PHP_EOL;

// hrtime(true) 精度更高
$before = hrtime(true);
usleep(100);
$after = hrtime(true);
echo "hrtime 差值: " . ($after - $before) . " ns" . PHP_EOL;

实战示例

请求耗时追踪

php
<?php
declare(strict_types=1);

class PerformanceTracker
{
    private array $timers = [];
    private int $requestStart;

    public function __construct()
    {
        $this->requestStart = hrtime(true);
    }

    public function start(string $name): void
    {
        $this->timers[$name] = ['start' => hrtime(true), 'end' => null];
    }

    public function end(string $name): float
    {
        if (!isset($this->timers[$name])) {
            throw new RuntimeException("计时器不存在: {$name}");
        }

        $this->timers[$name]['end'] = hrtime(true);
        $elapsed = $this->timers[$name]['end'] - $this->timers[$name]['start'];

        return $elapsed / 1_000_000; // 转为毫秒
    }

    public function getReport(): array
    {
        $report = [];
        foreach ($this->timers as $name => $timer) {
            $report[$name] = $timer['end'] !== null
                ? ($timer['end'] - $timer['start']) / 1_000_000
                : null;
        }

        $total = (hrtime(true) - $this->requestStart) / 1_000_000;
        $report['_total'] = $total;

        return $report;
    }
}

// 使用示例
$tracker = new PerformanceTracker();
$tracker->start('database');
// ... 数据库查询 ...
$dbTime = $tracker->end('database');

$tracker->start('api_call');
// ... API 调用 ...
$apiTime = $tracker->end('api_call');

$report = $tracker->getReport();
echo "数据库: {$report['database']} ms" . PHP_EOL;
echo "API: {$report['api_call']} ms" . PHP_EOL;
echo "总耗时: {$report['_total']} ms" . PHP_EOL;

注意事项

  • hrtime(true) 返回的值是单调递增的,不受系统时间调整影响
  • hrtime() 不适合用于获取当前日期时间,仅用于时间间隔测量
  • 对于一般场景,microtime(true) 足够使用

下一节

继续学习:GD 图像处理

参考链接