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

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

4

3 回答 3

21

JVM 和标准库中的很多东西都是延迟初始化的,以改善 JVM 启动时间。所以第一次执行该行

System.out.println("test");

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

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

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

于 2015-08-06T14:28:51.127 回答
17

许多事情会影响您的计算。

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

如果您想获得“更好”的结果,您应该运行更多次,并取平均值。

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

于 2015-08-06T14:29:32.300 回答
4

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

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

其中每一个都可能执行了很多初始化代码)。

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

于 2015-08-06T14:26:12.567 回答