0

私の自由な時間に、私は最近、マルチスレッドの数学演算のフレームワークを作成し、それをテストするために、千の素数の最初の数を計算しました。

しかし、もっと時間がかかる必要があったので、このコードをプライム計算に挿入しました。

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

長い間、私は64ビットマシンでコードを記述してコンパイルし、32ビットマシンでテストしていました。

次に、64ビットマシンで実行したところ、パフォーマンスに大きな違いがあることに気づきました。

同じコードで、完全に類似した64マシンの実行には100ミリ秒未満かかりますが、32マシンの実行には52000ミリ秒かかります(同じホスト上の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;
}
}

そして、これが私がコンパイルした.classファイルです。

今私の質問。

64ビットマシンを使用することでパフォーマンスが向上することは知っていますが、それではこの大きな違いを説明することはできません。それで、なぜこれが起こっているのか誰かが知っていますか?

4

2 に答える 2

4

64ビットJavaは常に-serverJITコンパイラを使用しますが、32ビットJVMはおそらく-clientJITコンパイラを使用していました。

C2別名。-サーバーコンパイラは次のようになります。

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

ループが何もしないことに気づき、それを削除します!何もしないループは、何にも最適化されません。

その最適化を失敗させるには、ループに何かを実行させる必要があります。iたとえば、それらすべてをXORして、結果を利用する必要があります。そうすると、ループはコンパイラーにとって実際の作業のように見え、コードは保持されます。

于 2012-02-19T21:36:34.363 に答える
3

Windowsでは、-clientデフォルトで32ビットおよび-server64ビットJVMにJVMを使用します。サーバーJVMは、何も実行しないコードの削除に積極的です。例:空のループ。このようなループは、ループの検出と除去にかかる時間に依存するため、カウント制限に関係なく、ほぼ同じ時間がかかることがわかります。同じメソッドに2番目のタイミングループを追加してみてください。最大値を何に設定しても、ほとんど時間がかからないことがわかります(無限ループではないと仮定)。これは、メソッドが2番目のループまでにコンパイルされるためです。開始します。

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

ところで:私はnanoTimeを使用して、少なくとも2、3秒間テストを繰り返し実行します。

于 2012-02-19T21:47:44.853 に答える