System.nanoTime()是Java中唯一适合高性能计时的时间源,仅记录真实纳秒差值且不受系统时间调整影响;需精准包裹被测逻辑、预热+多轮采样、封装为AutoCloseable计时器,并以纳秒为单位存储与统计。

System.nanoTime() 是 Java 中唯一适合构建高性能计时统计工具的时间源——它不提供“现在几点”,只忠实记录真实流逝的纳秒差值,且不受系统时间调整、NTP 同步或闰秒干扰。但直接裸用容易出错:漏写 end、混入干扰逻辑、单位换算失真、单次测量噪声大。真正高性能的统计工具,核心不在“调用 nanoTime”,而在如何包裹、采样、转换和聚合。
精准包裹被测逻辑,排除非目标开销
计时起点和终点必须紧贴你要评估的真实操作,比如一次 HashMap.get()、一段排序、一个 JSON 反序列化。任何日志打印、参数校验、锁等待、对象创建都应放在计时块之外。
- ✅ 正确:在 doBusinessWork() 方法调用前后各记一次 nanoTime
- ❌ 错误:在 Runnable.run() 开头 start,结尾 end,中间包含日志、异常处理、线程 sleep
- ⚠️ 注意:synchronized 阻塞、I/O 等待、GC 暂停都会计入耗时——若你测的是纯算法性能,这些就是噪声,需剥离
预热 + 多轮采样,对抗 JVM 与硬件波动
首次执行受类加载、JIT 编译、分支预测未就绪影响,结果偏高;单次测量易受上下文切换、缓存未命中、TLB miss 扰动。真实统计必须分阶段:
- 预热阶段:空跑目标逻辑 10000 次以上,确保 JIT 已编译、热点代码已优化
- 采样阶段:每轮执行 N 次(如 10000),记录总纳秒耗时,再算单次均值
- 统计阶段:重复 M 轮(建议 ≥30),取各轮均值的中位数(比平均值抗毛刺)
封装为 AutoCloseable 计时器,提升可读性与健壮性
手写 start/end 容易配对错误或遗漏。封装成轻量工具类,既避免重复代码,又支持 try-with-resources 自动管理:
立即学习“Java免费学习笔记(深入)”;
- 内部仅存一个 long start 字段,无状态、无 GC 压力
- 提供 elapsedNanos()、elapsedMicros()、elapsedMillis() 等语义清晰的方法
- elapsedMicros() 推荐用整数除法:(end - start) / 1000,向下取整,零浮点开销
- 如需小数精度(如绘图、平均值计算),用 elapsedNanos() / 1_000_000.0 转毫秒
保留原始纳秒值,延迟单位转换
高频压测中,统计系统(如 Micrometer、自定义 Histogram)应存储原始纳秒值,而非提前转成毫秒。原因有二:
- 避免多次整数除法放大截断误差(例如 1999ns → 1μs → 0ms,连续转换会丢失精度)
- 统一在展示层或聚合层做转换:P95/P99 统计时仍用纳秒,最终输出时按需转微秒(/1000)或毫秒(/1_000_000)
- 推荐字段命名如 costNanos,明确语义,防止后续误用



















