PHP 7.3+ 应优先使用 hrtime(true) 获取纳秒级单调时钟,精度高且抗回拨;7.2 及以下用 microtime(true) 即可,兼顾兼容性与实用性;polyfill 仅提供 API 兼容,不提升真实精度。

PHP 7.3+ 直接用 hrtime(true) 就行,别绕弯
它返回纳秒级整数,精度远超 microtime(true),且基于单调时钟(不受系统时间回拨影响),适合金融、高频计时等对时钟漂移敏感的场景。但注意:hrtime(true) 在 PHP 7.3+ 原生支持,无需安装扩展;若传 false(默认),返回 [seconds, nanoseconds] 数组,手动计算更麻烦,不推荐。
常见错误现象:
- 误以为
hrtime()返回的是“当前 Unix 时间戳”,其实它是自系统启动起的单调纳秒计数,不能直接转成日期 - 在 CLI 脚本里混用
$_SERVER['REQUEST_TIME_FLOAT'],但它在非 Web SAPI 下不存在,而hrtime(true)全环境可用
正确用法示例:
$start = hrtime(true); // 业务逻辑 $end = hrtime(true); $ns = $end - $start; echo "耗时: " . round($ns / 1e6, 3) . " 毫秒";
PHP 7.2 及更低版本没有 hrtime(),microtime(true) 是唯一合理选择
它返回浮点秒数(微秒精度),PHP 5.1+ 全支持,开销极低,结果可直接相减。所谓“精度不够”是误解——95% 的 Web 场景根本不需要纳秒级,反而因过度追求精度引入兼容性问题。
立即学习“PHP免费学习笔记(深入)”;
容易踩的坑:
- 调用
microtime()不带参数 → 返回字符串如"0.123456 1716830000",直接相减会得0(PHP 强制转整型) - 在循环体内高频调用
microtime(true)测单次迭代 → 函数自身开销约 0.5–1μs,会污染数据 - 把
microtime(true)和time()混用作“起始时间”,二者精度和语义完全不同
正确埋点位置比函数本身更重要:
- 测 Web 请求总耗时:放在框架中间件
handle()开头和return $next($request)之后 - 测数据库查询:在
$pdo->query()或 ORM 执行方法调用前后,而非 SQL 字符串拼接后
想在 PHP 7.2 模拟 hrtime()?用 Symfony Polyfill 最稳妥
Symfony 提供的 symfony/polyfill-php73 包含了 hrtime() 的兼容实现,最低支持 PHP 7.1。它不是“打补丁”,而是用 microtime(true) + 系统时钟校准逻辑模拟单调性,在绝大多数场景下行为一致。
安装方式:
composer require symfony/polyfill-php73
使用前需确保自动加载已生效(Composer 默认满足)。注意:
- polyfill 版本的
hrtime(true)仍受限于底层microtime()的精度(微秒),无法真正达到纳秒 - 它不解决 NTP 回拨问题(因依赖系统
gettimeofday),仅提供 API 兼容性 - 若项目已用 Xdebug 或 Blackfire,优先用它们做性能分析,polyfill 仅用于平滑升级过渡
别为毫秒/微秒精度纠结,先确认你真需要它
多数 PHP 应用的瓶颈不在计时精度,而在 I/O、SQL、网络或算法复杂度。用 microtime(true) 测出 12.345ms,和 hrtime(true) 测出 12345678ns,对优化决策没本质区别。
真正该警惕的是:
- 在阻塞操作(如
sleep()、fsockopen())中只看microtime()→ 它测的是 wall-clock time,不是 CPU 实际占用;此时应配合getrusage()看ru_utime.tv_sec - 把计时逻辑写进日志中间件却漏掉异常分支 →
try/catch外的耗时统计失效 - 生产环境靠手写
microtime()打点监控 → 应上 Prometheus + php-fpm_exporter 或 APM 工具
精度只是工具,关键是你用它回答什么问题。



















