system.nanotime()提供纳秒单位的单调时间差值,非绝对纳秒精度,实际分辨率通常为10–50纳秒;需预热、批量执行、多轮采样取中位数,并用durationns/1000.0保留浮点微秒精度。

System.nanoTime() 不是“纳秒级精度”的保证,而是提供纳秒单位的单调时间差值——它能告诉你两次调用之间过了多少纳秒,但这个数字是否真对应物理世界的纳秒,取决于底层系统。实际分辨率通常在 10–50 纳秒(Linux 常见 10–15 ns,Windows 可能达 100 ns 以上),虚拟机或容器中还可能受 CPU 配额影响出现非线性漂移。
为什么 nanoTime 的“纳秒”不能当真
返回值是 long 类型纳秒数,但硬件和 OS 并不总能稳定分辨 1 纳秒。比如连续两次调用相减得 0,不是代码没执行,而是计时器还没“动一下”。JIT 优化、线程调度、TLB 缺失、甚至 CPU 频率缩放,都会让单次测量值剧烈抖动。真正可靠的不是单个数字,而是大量采样后收敛的趋势。
怎么测才不算白测
- 预热必须做:用目标方法空跑 1 万–10 万次,确保 JIT 已编译、类已初始化、CPU cache 已预热
- 每轮批量执行:单次测量意义极小;建议每轮执行 1k–100k 次目标逻辑,只记一次总耗时,再除以次数
- 多轮独立采样:至少运行 20–30 轮,每轮结果作为独立样本,避免把 GC 或中断污染混进均值
- 用中位数而非平均值:P99 异常值(如一次 Full GC)会拉高平均,中位数更能反映典型性能
单位换算别踩坑
纳秒转微秒时,durationNs / 1000.0 得 double 类型浮点值,保留小数;而 durationNs / 1000 是整数截断,会系统性低估(如 1999 ns → 1 μs)。分析阶段推荐用浮点微秒,展示或打日志时可四舍五入到一位小数。
对比算法时的关键控制点
- 各自预热:A 和 B 必须分别完成完整预热,不能共用 JIT 状态
- 隔离状态:ArrayList、缓存、静态变量等不能复用,每次测量前重建或重置
- 统一执行规模:若 A 单次快(~20 ns)、B 慢(~150 ns),应提高每轮执行次数(如 100k 次),使总耗时远大于计时器误差
- 绑定 CPU 核心:Linux 下可用 taskset -c 0 启动 JVM,减少跨核迁移带来的延迟波动











