我有这段代码:
public static void main(String[] args) {
long f = System.nanoTime();
int a = 10 + 10;
long s =System.nanoTime();
System.out.println(s - f);
long g = System.nanoTime();
int b = 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10;
long h =System.nanoTime();
System.out.println(h - g);
}
使用此输出/ s:
测试1:
427
300
测试2:
533
300
测试3:
431
398
根据我的测试方案,为什么第int b = 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10;
行的执行速度比int a = 10 + 10;
快?
答案 0 :(得分:5)
众所周知,微型计算机很难做到正确,特别是在Java等“智能”语言中,编译器和Hotspot可以进行大量的优化。你几乎肯定没有测试你认为你正在测试的东西。阅读Anatomy of a Flawed Microbenchmark以获取更多详细信息和示例(现在这是一篇相当古老的文章,但原则与以往一样有效)。
在这种特殊情况下,我至少可以看到三个问题:
int a = 20;
和int b = 120;
)nanoTime
的粒度非常高。这与OS的负载相结合,意味着您在测量中的实验误差远远大于结果本身的大小。潜伏的潜在危险也可能更多。
故事的寓意是在真实条件下测试您的代码,以了解它的行为方式。单独测试小块代码并假设整体性能将是这些代码的总和是不准确的。
答案 1 :(得分:4)
首先。 Java编译器执行常量表达式的优化,因此编译时的代码将转换为:
int b = 120;
结果,JVM几乎在同一时间执行a=20
和b=120
分配。
第二个。你执行大系统的短测量(我的意思是包括操作系统,交换过程,另一个运行过程的整个计算机......)。因此,您可以在非常短的时间段内获得随机系统的快照。这就是为什么你不能推断a
作业比b
更快的真假。为了证明这一点,你必须将代码测量放在相当大的循环中 - 做大约1,000,000次。如此大的重复可以让你平滑期望(在这个词的数学意义上)
答案 2 :(得分:2)
这不是衡量效果的正确方法。
首先,不要测量这么小的代码。 相反,像@NilsH建议的那样,将其称为数百万次, 并通过将经过的时间除以通话次数来获得平均时间。
其次,JVM可能会对您的代码执行优化, 所以你需要给它一个“热身”的时间。 在没有测量时间的情况下,让几百万人“干”运行, 而不是开始你的测量。