【问题标题】:Same test get different result with jdk6 and jdk7相同的测试使用 jdk6 和 jdk7 得到不同的结果
【发布时间】:2012-08-24 17:48:11
【问题描述】:

我在尝试比较数据类型“int”和“long”的性能时遇到了这个奇怪的问题,基本上我有两个单元测试:

@Test
public void testLongOperationPerformance(){
    StopWatch sw = new StopWatch();
    sw.start();
    long count = 0l;
    for(int i = 0; i < Integer.MAX_VALUE; i ++){
        count++;
    }
    sw.stop();
    System.out.println(count);
    System.out.println(sw.elaspedTimeInMilliSeconds());
}

@Test
public void testIntegerOperationPerformance(){
    StopWatch sw = new StopWatch();
    sw.start();
    int count = 0;
    for(int i = 0; i < Integer.MAX_VALUE; i ++){
        count++;
    }
    sw.stop();
    System.out.println(count);
    System.out.println(sw.elaspedTimeInMilliSeconds());
}

这两个单元测试做同样的事情,不同的是一个使用 int 作为 counter 的数据类型,另一个使用 long 作为那个。 结果:

jdk6u32 (64 bit):
test with long
2147483635
96
test with int
2147483647
2

jdk7 (64 bit)
test with long
2147483647
1599
test with int
2147483647
1632

我注意到了:

  1. 在 jdk6u32 中,使用 int 进行测试比使用 long 进行测试要快得多
  2. 在 jdk6u32 中,int 测试和 long 测试的测试结果不同
  3. 在 jdk7 中,两个测试的速度差不多,但都比 jdk6u32 慢得多
  4. 在 jdk7 中,两个测试得到了相同的结果

谁能解释一下为什么会这样?

【问题讨论】:

  • 你是说 jdk6u32 返回错误的数字(缺少 12 次迭代)?
  • 你确定你发布的代码和结果吗:使用 JDK 的长测试正在消耗循环的一部分似乎很奇怪。
  • 您还应该选择不那么琐碎的测试。编译器或 JIT 可以优化您的代码并轻松地立即删除循环,因为最后的计数值可以很容易地计算出来。

标签: java performance long-integer java-7 jdk6


【解决方案1】:

Java JIT 特别擅长消除无用的代码。在您的示例中,循环

long count = 0l;
for(int i = 0; i < Integer.MAX_VALUE; i ++){
    count++;
}

可以替换为

long count = 0l;
count += Integer.MAX_VALUE * 1;

您正在计时的是检测和消除循环需要多长时间。这个时间可能取决于它之前所做的事情,所以我建议以不同的顺序测试循环,看看是否会改变结果。

在 Java 6 和 7 中,许多循环优化未正确优化。

例如对于某些更新,这个无限循环并不总是无限的

for(int i=0; i < Integer.MAX_VALUE; i += 2)

因此,某些更新会根据它们是否适用于该版本而开启或关闭不同的优化。我建议尝试最新版本的 Java 7,看看它是否有所作为。

【讨论】:

  • 谢谢彼得。我不明白的是,如果 JDK6 对测试代码进行了优化,为什么 jdk7 没有。
  • 另外,即使 JIT 做了代码替换,结果也不应该不同,对吧? jdk6 和 long 类型的结果甚至都不正确。
猜你喜欢
  • 2014-11-27
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 2013-03-04
  • 2021-12-15
  • 2019-01-30
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多