相同的测试与jdk6和jdk7得到不同的结果

sei*_*iya 0 java performance jdk6 java-7 long-integer

在尝试比较数据类型'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());
}
Run Code Online (Sandbox Code Playgroud)

这两个单元测试正在做同样的事情,不同的是一个使用int作为计数器的数据类型,另一个使用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
Run Code Online (Sandbox Code Playgroud)

我注意到:

  1. 在jdk6u32中,使用int测试比使用long测试快得多
  2. 在jdk6u32中,test与int和test之间的测试结果不同
  3. 在jdk7中,两个测试速度大致相同,并且它们都比jdk6u32慢得多
  4. 在jdk7中,两个测试都得到了相同的结果

任何人都可以解释为什么会这样吗?

Pet*_*rey 6

Java JIT特别擅长消除无法执行任何操作的代码.在你的例子中,循环

long count = 0l;
for(int i = 0; i < Integer.MAX_VALUE; i ++){
    count++;
}
Run Code Online (Sandbox Code Playgroud)

可以替换为

long count = 0l;
count += Integer.MAX_VALUE * 1;
Run Code Online (Sandbox Code Playgroud)

您的计时是检测和删除循环所需的时间.这个时间可以取决于它之前做了什么,所以我建议以不同的顺序测试循环,看看是否会改变结果.

在Java 6和7中,许多循环优化被错误地优化.

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

for(int i=0; i < Integer.MAX_VALUE; i += 2)
Run Code Online (Sandbox Code Playgroud)

出于这个原因,某些更新具有不同的优化开启或关闭,具体取决于它们是否适用于该版本.我建议尝试使用最新版本的Java 7,看看它是否有所作为.