2013-06-03 93 views
1

的时间我有这样的代码:爪哇 - 执行

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); 

} 

有了这个输出/秒:
测试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

在主方法中的_one_运行结束这是太不确定。至少在一个循环内运行几百万次。 – NilsH

+0

Micheal 请在下面检查URL。 Java中Integer类型的到期池行为会导致后者运行得更快,因为整数b执行的时间10已经在池中。希望这可以帮助。 http://stackoverflow.com/questions/13098143/java-integer-constant-pool –

+0

我每次运行这段代码都会得到不同的结果,从0到600,有时其中一个是0。这些操作太快,您无法一次测试。 – Djon

回答

5

Microbenchmarks非常难以正确使用,特别是在诸如Java的“智能”语言中,编译器和Hotspot可以进行大量优化。你几乎肯定没有测试你认为你正在测试的东西。请阅读Anatomy of a Flawed Microbenchmark了解更多详细信息和示例(现在这是一篇相当古老的文章,但其原理与以往一样有效)。

在这种特殊情况下,我可以看到了蝙蝠的权利至少有三个问题:

  • 的代码不会在所有执行任何另外,因为编译器将分配变量的编译时常数值。 (即,就好像你的代码被读取为int a = 20;int b = 120;
  • 在大多数系统上,nanoTime的粒度相当高。这与操作系统的负载相结合,意味着您的测量实验误差远大于结果本身的大小。
  • 即使增加发生,你还没有“热身”虚拟机;通常无论你放在第二位的操作会因为这个原因而显得更快。

潜在的潜在危害也可能存在。

故事的寓意是在真实世界的条件下测试你的代码,看它的行为如何。绝不能单独测试小块代码,并假设整体性能是这些块的总和。

+0

这一个清理我的路径。我的意思是,所有的答案都有相同的观点。但是这篇文章阐述了我做错了什么。 –

4

首先是。 Java编译器进行常量表达式的优化,使您在编译时的代码将被转换为:

int b = 120; 

至于结果JVM执行分配给a=20b=120同时附近。

第二个。你对大系统进行简短的测量(我的意思是整个计算机,包括操作系统,交换过程,另一个运行过程......)。所以你可以在很短的时间内得到随机系统的快照。这就是为什么你不能推断真假,a分配比b更快。为了证明这一点,你必须将代码测量放在相当大的循环中 - 大致执行1,000,000次。如此大的重复可让您顺利进行期望(在数学意义上的这个词)

+2

这可以通过检查生成的字节码('bipush 20'和'bipush 120')来确认。 – assylias

+1

大系统还包括JVM本身 – LeGEC

2

这不是衡量表现的正确方法。

首先,不要测量这么小的一段代码。 而是像@NilsH所建议的那样拨打数百万次, 并通过将已用时间除以通话次数获得平均时间。其次,JVM可能对您的代码 执行优化,因此您需要给它一个“预热”时间。 在开始测量之前,不需要测量任何时间就可以让几百万的“干燥”运行。