microtime(true) 是PHP测脚本耗时最可靠方法,返回微秒精度浮点数,相减得真实耗时,不受时区和系统时钟跳变影响;time()仅秒级精度,microtime()无参数返回字符串易出错;$_SERVER['REQUEST_TIME_FLOAT']记录请求接收时间而非脚本执行起点,CLI下不存在且部分SAPI可能不填充。

用 microtime(true) 获取执行时间最可靠
PHP 里测脚本耗时,microtime(true) 是唯一推荐的起点。它返回带微秒精度的浮点数(单位秒),相减就能得到真实耗时,不受时区、系统时钟跳变影响。
常见错误是用 time() ——它只精确到秒,短脚本全显示 0;或者用 microtime() 不带参数,返回字符串,得手动解析,容易出错。
- 必须传
true参数,否则返回"0.123456 1712345678"这种格式,拆分麻烦还易错 - 放在脚本开头和结尾调用,别漏掉
ob_start()或输出缓冲开启前的初始化开销 - CLI 模式下没问题,但 Web 环境中注意:如果用了输出缓冲或框架中间件,实际耗时可能比你测的长
为什么不能用 $_SERVER['REQUEST_TIME_FLOAT']
这个变量看起来方便,但它记录的是 PHP 接收到请求那一刻的时间戳,不是脚本真正开始执行的时间。尤其在 Apache 的 mod_php 或某些 FastCGI 配置下,请求到达和 index.php 开始运行之间可能有几十毫秒延迟。
典型现象:你用 microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'] 算出来是 120ms,但用前后 microtime(true) 相减却是 150ms —— 差那 30ms 就是 PHP 自身加载、路由解析等前置动作。
立即学习“PHP免费学习笔记(深入)”;
-
$_SERVER['REQUEST_TIME_FLOAT']适合粗略估算“整个请求生命周期”,不适合测单个函数或脚本块 - 它在 CLI 模式下根本不存在,直接
Notice: Undefined index - 某些 SAPI(如 PHP-FPM 的某些配置)可能不填充该字段,导致返回 0 或空值
封装成函数要注意精度丢失和浮点误差
很多人会写个 timer_start() / timer_end() 函数,但没注意 PHP 浮点数在小数位上的表现。比如 0.000001 秒级差异,直接 echo 可能显示为 0,var_dump 却能看到。
示例:$start = microtime(true); usleep(100); $end = microtime(true); echo $end - $start; 可能输出 0.000123 或 1.23456E-4,取决于 PHP 版本和输出上下文。
- 用
sprintf('%.6f', $end - $start)固定小数位,避免科学计数法干扰判断 - 别用
==比较两个微秒差值,改用abs($a - $b) - 如果要记录日志,建议统一转成微秒整数:
(int)(($end - $start) * 1000000),避免浮点存储歧义
Web 环境下真实耗时 ≠ microtime 差值
你在代码里测出 50ms,但浏览器 Network 面板看到 TTFB 是 220ms,这不矛盾——microtime 只覆盖 PHP 执行段,不包括 DNS 查询、TCP 握手、Nginx 转发、静态资源加载等环节。
更隐蔽的问题:如果你启用了 OPcache,首次请求慢、后续快;如果用了 APCu 或 Redis 缓存,命中率波动也会让 microtime 结果飘忽。
- 压测时务必清空 OPcache(
opcache_reset())并禁用外部缓存,否则数据不可比 - Apache 的
mod_status或 Nginx 的$request_time变量,才是服务端完整请求耗时参考 - 想定位瓶颈,不要只看总时间,配合
xdebug或blackfire看函数级火焰图
真正难的不是算出一个数字,而是搞清楚这个数字到底代表哪一段执行过程。同一行 microtime(true) 放在 require 前后,结果可能差出 10ms —— 这 10ms 是文件 I/O,不是你的业务逻辑。











