java 32和64 bit之间的空循环的巨大性能差异

时间:2012-02-19 21:25:43

标签: java performance 32bit-64bit jvm-hotspot

在我的空闲时间里,我最近制作了一个多线程数学运算的框架,并测试它,我计算了千元素数的第一个数。

但我需要花费更多时间,所以我将此代码插入到主要计算中:

for (int i = 0; i < 1000000; i++)
{
    // Nothing.
}

很长一段时间,我在64位机器上编写并编译代码,并在许多32位机器上进行测试。

然后我在64位机器上运行它,并注意到了巨大的性能差异。

使用相同的代码,完全类似的64台机器需要<100ms才能完成,32台机器使用~52000ms(同一台主机上有2台虚拟机)。

我已经在不同的计算机上测试过Windows和Ubuntu,并使用相同的.class文件,我仍然可以获得32位与64位差异。

这是一个快速代码,您可以使用复制性能差异。

import java.util.ArrayList;
import java.util.Collection;
public class Test {
public static void main(String[] args)
{
    long start = System.currentTimeMillis();
    int j = 2;
    ArrayList<Integer> res = new ArrayList<Integer>();
    for (int k = 0; k < 50000; k++)
    {
        Collection<Integer> partres = work(k);
        if (partres != null)
            res.addAll(work(k));
    }
    long end = System.currentTimeMillis();
    System.out.println("Done in " + (end-start) + " ms.");
}
public static Collection<Integer> work(Integer j) {
    for (int i = 0; i < 1000000; i++)
    {
        // Nothing.
    }
    if (isPrime(j))
    {
        ArrayList<Integer> res = new ArrayList<Integer>();
        res.add(j);
        return res;
    }
    else
        return null;
}
static boolean isPrime(int n) {
    if (n == 2) return true;
    if (n%2==0) return false;
    for(int i = 3; i * i <= n; i += 2) 
        if(n%i==0)
            return false;
    return true;
}
}

here is the .class file i compiled it to.

现在我的问题。

我知道使用64位机器会带来性能提升,但这并不能解释这种巨大的差异。所以有人知道为什么会这样吗?

2 个答案:

答案 0 :(得分:4)

64位Java总是使用-server JIT编译器,而32位JVM可能使用-client JIT编译器。

当C2又名。 -server编译器看到如下内容:

for (int i = 0; i < 1000000; i++)
{
  // Nothing.
}

它会注意到循环什么也没做,删除了它!你的循环什么都不做,将被优化为什么。

为了阻止这种优化,你必须让循环做一些事情 - 它可以将所有i放在一起,例如 - 并且使用结果。然后循环看起来像编译器的实际工作,代码将被保留。

答案 1 :(得分:3)

在Windows上,默认情况下,-client JVM用于32位,-server用于64位JVM。服务器JVM在删除无法执行任何操作的代码方面更为积极。例如空循环。无论计数限制如何,您都会发现这样的循环需要大约相同的时间,因为它取决于检测和消除循环所需的时间。尝试在同一个方法中添加第二个定时循环,你会发现无论你设置的最大值是什么,它几乎都没有时间(假设它不是一个无限循环)这是因为该方法将在第二个循环时编译启动。

http://docs.oracle.com/javase/1.5.0/docs/guide/vm/server-class.html

BTW:我会使用nanoTime并重复运行你的测试至少几秒钟。