web-dev-qa-db-ja.com

Java vs.NETパフォーマンス

.NET4.5とJava 8のコンピューターのパフォーマンスを比較するためにこの小さなコードを書いた後、私は非常に驚きました。

class ArrayTest
{
    public int[][] jagged;

    public ArrayTest(int width, int height)
    {
        Height = height;
        Width = width;
        Random rng = new Random();
        jagged = new int[width][];
        for (int i = 0; i < height; i++)
        {
            jagged[i] = new int[width];
            for (int j = 0; j < jagged[i][j]; j++)
            {
                jagged[i][j] = rng.Next(2048);
            }
        }
    }
    public int this[int i, int j]
    {
        get
        {
            return jagged[i][j];
        }
        set
        {
            jagged[i][j] = value;
        }
    }

    public void DoMath(ArrayTest a)
    {
        for (int i = 0; i < Height; i++)
        {
            for (int j = 0; j < Width; j++)
            {
                this[i, j] *= a[i, j];
            }
        }
    }

    public int Height { get; private set; }

    public int Width { get; private set; }
}



class Program
{
    static void Main(string[] args)
    {
        Random rng = new Random();
        const int loop = 10;
        int width = 10000,
            height = 10000;

        ArrayTest a1 = new ArrayTest(width, height),
            a2 = new ArrayTest(width, height);


        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < loop; i++)
        {
            a1.DoMath(a2);
        }
        sw.Stop();

        Console.WriteLine("Time taken: " + sw.ElapsedMilliseconds);

        Console.ReadKey();
    }
}

これがJavaバージョン:

    public class ArrayTest {
    private int width, height;
    private int[][] array;

    public ArrayTest(int width, int height) {
        this.width = width;
        this.height = height;
        array = new int[height][width];
        Random rng = new Random();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                array[i][j] = rng.nextInt(2048);
            }
        }
    }

    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }
    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }
    public int[][] getArray() {
        return array;
    }

    public void doMath(ArrayTest a) {
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                array[i][j] *= a.getArray()[i][j];
            }
        }
    }

}

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        final int loops = 10;
        int width = 10000, height = 10000;
        ArrayTest a1 = new ArrayTest(width, height),
                a2 = new ArrayTest(width, height);

        long start, end;


        start = Java.lang.System.currentTimeMillis();
        for (int i = 0; i < loops; i++) {
            a1.doMath(a2);
        }
        end = Java.lang.System.currentTimeMillis();
        System.out.println("Elapsed time: " + (float)(end - start));
    }

}

私のコンピューターでは、このC#コードの実行に約5200ミリ秒かかり、Javaバージョンの実行には約2800ミリ秒かかります(!!!)。実際には、.NETバージョンの方が高速に実行されると期待していました(または少なくともJavaよりも)に近いですが、この結果に非常に驚いています。

注:VisualStudioの外部でリリースモードでコンパイルされた.NETバージョンを実行しました。

誰かがこの結果を説明できますか?これは本当に正しいですか? C#.NETバージョンが実行速度でJava 1に近づくように、このコードを書き直すにはどうすればよいですか?

[編集]

まあ、これは本当に有効なベンチマークや公正な比較ではないことはわかっていますが、C#.NETバージョンが実行速度でJava 1に近づくようにこのコードを書き直すにはどうすればよいですか?試してみましたか?どのような形式でも(ギザギザの配列を直接、ゲッターを介して操作するなど)、テストの実行速度はさらに遅くなります。

[編集2]

幅と高さが500、ループが5000になるようにテストを編集しました。これで、.NETバージョンでは約6300ミリ秒、Javaバージョンでは約3700ミリ秒)テストを複数回実行しました。もちろん、各バージョン。

[編集3]

2D配列の代わりにフラット配列を使用して同様のテストを作成したところ、今回は.NETバージョンがJavaと同等またはそれ以上の速度で実行されます。それでそれですか? C#.NETのギザギザの配列は、Javaの多次元配列よりも遅いだけですか?

8
Yan Paulo

あらゆる種類のベンチマークやパフォーマンス分析を行うときはいつでも、多くの質問をし、(言い換えれば Tanenbaum )、「1メートルトンの塩」で特定の結果を得る必要があります。

しかしながら ....

私はあなたのコードをコピーして貼り付けました、そしてこれは私が得たものです:

Compiler      Version   Timing
--------      -------   ------
MSVS 2012     C# 5      4448.0
Eclipse Luna  JRE 1.7    977.0

したがって、JavaプログラムはC#プログラムより4.5倍高速に実行されました。

また、MSVS「プロファイリングウィザード」を実行しました。

https://msdn.Microsoft.com/en-us/library/dd264959.aspx

MSVS Profiler Summary大きな画像

スクリーンショットからわかるように、このプロファイルの「Big Pig」は、ArrayTest.get_item(int32、int32)であり、NEARLY HALF実行時間の:

enter image description here大きな画像

12
FoggyDay

単一のインスタンスに基づいてパフォーマンスを判断することはできません。複数のインスタンスに対してそれを行う必要があります。パフォーマンスに関する具体的な回答が必要な場合は、 quorablog または [〜#〜] so [〜#〜] を読むことをお勧めします。

1
Abhishek