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

时间:2015-08-06 14:22:30

标签: java system nanotime

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

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

第一个和第二个运行时之间区别的原因是什么?提前感谢=)

3 个答案:

答案 0 :(得分:21)

JVM和标准库中的许多内容都被懒惰地初始化以改善JVM启动时间。所以你第一次执行这行

System.out.println("test");

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

您可以在Java中对大量API调用观察到相同的效果。

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

答案 1 :(得分:17)

很多事情都会影响你的计算。

您计算机上的其他进程怎么样?您是否认为 JVM正在升温?也许垃圾收集?所有这些因素和更多因素都会导致这种行为。

如果你想获得“更好”的结果,你应该多运行一次,然后取平均值。

这就是为什么您应该知道如何使用Java对事物进行基准测试,请参阅How do I write a correct micro-benchmark in Java?

答案 2 :(得分:4)

JVM花了一些时间来初始化所有需要的对象,访问系统时间,系统输出流等......你有两种方法发生在:

System.nanoTime() 
System.out.println() 

每个人都可以执行很多初始化代码。)

每次连续呼叫都要快得多,因为这已经完成了。因此,当人们对性能应用程序进行基准测试时,通常会放弃预热和冷却阶段(例如,第一次和最后15分钟)。