【发布时间】:2017-02-11 01:16:01
【问题描述】:
在阅读了有关 Stack Overflow 上的类似主题后,我编写了以下代码来了解 System.nanoTime() 的一致性。
它只是在对空的 void 函数进行方法调用之前和之后调用 System.nanoTime(),记录过程中经过的时间。但是,正如您在结果中看到的那样,第一次调用总是花费最长的时间。这是什么原因?
public class Test {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
double start = System.nanoTime();
foo();
double end = System.nanoTime();
double diff = end - start;
System.out.println("Diff: " + diff);
}
}
public static void foo() {
}
}
结果:
Diff: 2765.0
Diff: 509.0
Diff: 236.0
Diff: 238.0
Diff: 230.0
Diff: 539.0
Diff: 359.0
Diff: 356.0
Diff: 380.0
Diff: 353.0
请注意,我确实读过这个问题:Why does first call to java.io.File.createTempFile(String,String,File) take 5 seconds on Citrix?
此外,此链接有助于将来参考,但不一定回答我的具体问题:How do I write a correct micro-benchmark in Java?
【问题讨论】:
-
一句话:“缓存”(在各种层上)。一旦涉及到缓存,第二次做同样的事情就会快得多。另外,2 微秒的差异确实没什么好担心的,为什么要将
nanoTime转换为浮点数? -
那个方法真的是空的吗?也许 JVM 会发现并完全优化它?请做两个跟进:a)在没有任何代码或方法调用的情况下测量 nanoTime 差异 b)在
foo方法中进行一些小计算。 -
JVM 上的微基准测试很难,因为JIT compiler 可以在代码运行一段时间后巧妙地改变代码的工作方式。正确的方法是使用真正的基准测试框架,如 jmh
-
并非总是如此。我恢复了你的实验,有时它不是第一个需要最长时间的实验。我的jdk1.8和操作系统win10。
-
运行代码更长例如
20_000次,它将内联该方法,并将减少调用 System.nanoTime() 所需的时间