为什么第一次nanoTime()调用和连续调用之间的时间差异如此之大?

2022-09-03 09:08:14

所以我的问题更笼统。我有以下简单的代码:

for(int i=0;i<10;i++){
    long starttime=System.nanoTime();
    System.out.println("test");
    long runtime=System.nanoTime()-starttime;
    System.out.println(i + ":" +"runtime="+runtime);
}

我收到以下输出:

test
0:runtime=153956
test
1:runtime=15396
test
2:runtime=22860
test
3:runtime=11197
test
4:runtime=11197
test
5:runtime=12129
test
6:runtime=11663
test
7:runtime=11664
test
8:runtime=53185
test
9:runtime=12130

第一个运行时和第二个运行时之间存在差异的原因是什么?提前致谢=)


答案 1

无论是在 JVM 中还是在标准库中,很多东西都被懒惰地初始化,以缩短 JVM 启动时间。所以第一次执行行

System.out.println("test");

一个重量级的初始化过程发生了。完成它的时间包含在您的第一次测量中。后续调用沿着状态已初始化的快速路径进行。

您可以在Java中的许多API调用上观察到相同的效果。

当然,还有更多因素会影响完成任何给定方法调用所需的时间,特别是如果它在其路径上包含系统调用。但是,第一次调用延迟中的异常值是特殊的,因为它具有潜在的确定性原因,因此可以可靠地重现。


答案 2

许多因素都会影响您的计算。

您机器上的其他进程呢?您是否考虑过 JVM 预热?也许是垃圾回收?所有这些因素以及更多因素都会导致这种行为。

如果你想得到“更好”的结果,你应该运行它更多的时间,并取平均值。

这就是为什么你应该知道如何在Java中对事物进行基准测试,请参阅如何在Java中编写正确的微基准测试?


推荐