高精度基准测试需构建抗干扰闭环:充分预热触发jit编译,批量执行(1000–10⁵次)后取均值,多组采样剔除极值,并控制硬件/os环境。

用 System.nanoTime() 做高精度基准测试,核心不是“调两次取差”,而是构建一套抗干扰、可复现的测量闭环。它本质是把 JVM 运行时的不确定性(JIT、GC、调度)当作噪声来压制,而不是忽略。
预热必须做,且要足够充分
刚加载的方法处于解释执行状态,性能远低于 JIT 编译后的版本。不预热,测的其实是“编译器启动过程”,不是代码本身。
- 对简单方法(如加法、getter),空跑 1 万~10 万次即可触发 C1/C2 编译
- 对含分支、异常或对象分配的方法,建议预热 50 万次以上,并观察
-XX:+PrintCompilation输出确认编译完成 - 预热期间避免日志、IO、同步块——这些会污染 JIT 决策路径
测量必须批量,不能单次
System.nanoTime() 自身调用开销约 10–50 纳秒。若待测逻辑本身仅耗时 20 纳秒,单次测量结果基本是噪声。
- 每轮测量执行 1000~100000 次目标操作,只在循环前后各调一次
nanoTime() - 总耗时除以次数,得到单次均值(单位:纳秒),再转微秒时用
durationNs / 1000.0保留小数 - 避免在循环体内反复调用
nanoTime(),否则计时开销会主导结果
采样必须多组,且剔除极值
一次测量受 GC、中断、CPU 频率切换等影响极大。单个数字毫无统计意义。
- 运行至少 10~30 组独立测量(每组含完整预热 + 批量执行)
- 每组输出一个“N 次总耗时”样本,例如 “100 万次耗时:124892345 ns”
- 剔除首尾各 10% 的样本(或直接取中位数),排除 STW GC 或调度尖峰污染
环境必须可控,否则数据失真
硬件和 OS 层干扰常比 JVM 层更大,容易被忽略。
- Linux 下禁用节能模式:
cpupower frequency-set -g performance - 绑定单核运行:
taskset -c 0 java YourBenchmark,减少跨核迁移 - 避免在测量循环内创建对象,防止 Young GC 插入;必要时加
-Xlog:gc*:file=gc.log核查 - 确保待测方法有实际副作用(如写入
volatile变量或累加到全局 long),否则 JIT 可能整个优化掉逻辑











