Java与.NET性能

Yan*_*ulo 8 c# java clr performance jvm

在我编写这个小代码以比较我的计算机中的.NET 4.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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是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));
    }

}
Run Code Online (Sandbox Code Playgroud)

在我的计算机中,这个C#代码运行大约5200ms,Java版本大约需要2800ms(!!!).我实际上期望.NET版本比Java运行得更快(或至少接近),但对此结果感到非常惊讶.

注意:我在Visual Studio外部运行了在发布模式下编译的.NET版本.

有人可以解释这个结果吗?这是真的吗?我怎么能重写这段代码,以便C#.NET版本在执行速度上更接近Java?

[编辑]

好吧,我知道这不是一个真正有效的基准测试或公平的比较,但我怎么能重写这个代码,以便C#.NET版本在执行速度上更接近Java?尝试任何形式(直接操纵锯齿状数组,通过吸气剂等),但测试运行速度更慢.

[编辑2]

编辑测试,以便我有宽度和高度= 500,并且loop = 5000.现在我得到大约6300ms的.NET版本,大约3700ms的Java版本.当然,每个版本都会多次运行测试.

[编辑3]

刚刚使用平面数组而不是2D数组编写了类似的测试,这次.NET版本的运行速度与Java相同甚至更快.那是这样的吗?C#.NET的锯齿状数组比Java的多维数组要慢?

Fog*_*Day 12

无论何时进行任何基准测试或性能分析,您都需要提出很多问题,并采取任何特定结果(用Tanenbaum的话来说),"一公吨盐".

但是......

我复制粘贴你的代码,这就是我得到的:

Compiler      Version   Timing
--------      -------   ------
MSVS 2012     C# 5      4448.0
Eclipse Luna  JRE 1.7    977.0
Run Code Online (Sandbox Code Playgroud)

因此Java程序的运行速度比C#程序快4.5倍.

我还运行了MSVS"Profiling Wizard":

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

MSVS Profiler摘要 大图

正如您可以从屏幕截图中看到的那样,此配置文件中的"Big Pig"是ArrayTest.get_item(int32,int32),它几乎消耗了执行时间的HALF:

在此输入图像描述 大图

  • 我们试图将Java中的直接访问与C#中的指针访问进行比较.简单来说,为了存储/加载数组的下一个值,java使用带有指针bump`inc`的普通`mov`,c#使用更昂贵的操作`lea`来计算每个加载/存储的有效地址值!我已将测试更改为直接访问并获得了与java和C#相同的结果 (7认同)

Abh*_*hek 1

你不能根据单个实例来判断性能。您需要为多个实例执行此操作。如果您想要有关性能的具体答案,我建议您阅读quora博客SO