C#.NET和Java中的2d阵列性能
我编写了一些代码来测试C#(.NETCLR)和Java(Java8,Windows)中数组的性能。对于普通平面阵列,.NET显示出比Java快一点 当我编写一些测试2d数组(使用锯齿数组)的代码时,我注意到Java和C#之间存在明显的差距。Java版本运行速度比C快2倍以上 这是我的C代码:C#.NET和Java中的2d阵列性能,java,c#,.net,arrays,performance,Java,C#,.net,Arrays,Performance,我编写了一些代码来测试C#(.NETCLR)和Java(Java8,Windows)中数组的性能。对于普通平面阵列,.NET显示出比Java快一点 当我编写一些测试2d数组(使用锯齿数组)的代码时,我注意到Java和C#之间存在明显的差距。Java版本运行速度比C快2倍以上 这是我的C代码: 类数组测试 { 公共int[][]锯齿形; 公共阵列测试(整数宽度、整数高度) { 高度=高度; 宽度=宽度; 随机rng=新随机(); 锯齿状=新整数[高度][]; 对于(int i=0;i
类数组测试
{
公共int[][]锯齿形;
公共阵列测试(整数宽度、整数高度)
{
高度=高度;
宽度=宽度;
随机rng=新随机();
锯齿状=新整数[高度][];
对于(int i=0;i
在我的电脑中,被测部分大约需要2200ms才能运行
以下是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(1024);
}
}
}
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.array[i][j];
}
}
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
final int loop = 500;
int width = 800,
height = 800;
ArrayTest a1 = new ArrayTest(width, height),
a2 = new ArrayTest(width, height);
long start, end;
start = java.lang.System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
a1.doMath(a2);
}
end = java.lang.System.currentTimeMillis();
System.out.println("Elapsed time: " + (end - start));
}
}
公共类数组测试{
私人int宽度、高度;
私有int[][]数组;
公共阵列测试(整数宽度、整数高度){
这个。宽度=宽度;
高度=高度;
数组=新整数[高度][宽度];
随机rng=新随机();
对于(int i=0;i
运行大约需要930毫秒
到目前为止,它是C#2200ms与java930ms的对比
但是,当我将C#方法更改为如下所示时:
public void DoMath(ArrayTest a)
{
int[][] _jagged = this.jagged,
_a = a.jagged;
int[] __jagged, __a;
for (int i = 0; i < _jagged.Length; i++)
{
__jagged = _jagged[i];
__a = _a[i];
for (int j = 0; j < __jagged.Length; j++)
{
__jagged[j] *= __a[j];
}
}
}
公共无效域(ArrayTest a)
{
int[][]\u jagged=this.jagged,
_a=a.锯齿状;
int[]\uuuuuuuuuuuuuuuuua型;
对于(int i=0;i<_jagged.Length;i++)
{
__锯齿状的;
__a=_a[i];
对于(int j=0;j<\uu jagged.Length;j++)
{
__锯齿状[j]*=u a[j];
}
}
}
然后我的C#代码变得和Java一样快!(930毫秒)
我花了很长时间才找到这段代码,我仍然不知道为什么它比第一个版本更快(而且更难看)
因此,以下是我的问题:
需要明确的是:它不是一个微观基准或类似的东西。我只想通过2d数组使操作比Java更快(或与Java一样快),我更喜欢使用更干净的代码。尝试进行以下非常小的更改:
public void DoMath(ArrayTest a)
{
int height = Height;
int width = Width;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
jagged[i][j] *= a.jagged[i][j];
}
}
}
公共无效域(ArrayTest a)
{
int高度=高度;
整数宽度=宽度;
对于(int i=0;i
这几乎使我的机器的性能提高了三倍。您是否将C#项目设置为在发布模式或调试模式下运行?这有很大的区别
以下是我的结果:
- 如您所知:5555ms(在我的笔记本电脑上运行,调试模式,已连接调试器)
- 经过上述修改(与上述条件相同):1808ms
- 在调试器(CTRL-F5)外部以发布模式运行: 907毫秒
Height
和Width
属性的调用。每次循环时,它都会转到属性,然后属性必须转到backing字段以获取值,然后返回
因为您在Java中使用的是字段而不是属性,所以您不必
public void DoMath(ArrayTest a)
{
int height = Height;
int width = Width;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
jagged[i][j] *= a.jagged[i][j];
}
}
}
public void DoMath(ArrayTest a)
{
//Stopwatch st = new Stopwatch();
//st.Start();
//for (int i = 0; i < Height; i++)
Parallel.For(0, Height, (i) =>
{
for (int j = 0; j < Width; j++)
{
jagged[i][j] *= a.jagged[i][j];
}
});
//st.Stop();
//Console.WriteLine(st.ElapsedMilliseconds);
}
public void DoMath(ArrayTest a)
{
Parallel.For(0, Height, (i) =>
{
int[] _jagged = jagged[i];
int[] _a = a.jagged[i];
for (int j = 0; j < _jagged.Length; j++)
{
_jagged[j] *= _a[j];
}
});
//st.Stop();
}
class ArrayTest
{
public int [][] jagged;
public ArrayTest(int width, int height)
{
Height = height;
Width = width;
Random rng = new Random();
jagged = new int[height][];
for (int i = 0; i < height; i++)
{
jagged[i] = new int[width];
for (int j = 0; j < width; j++)
{
jagged[i][j] = rng.Next(1024);
}
}
}
public int Height { get; private set; }
public int Width { get; private set; }
public int this[int i, int j]
{
get
{
return jagged[i][j];
}
set
{
jagged[i][j] = value;
}
}
public void DoMath(ArrayTest a)
{
int width = Width, height = Height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//jagged[i][j] *= a.jagged[i][j];
jagged[i][j] = jagged[i][j] * a.jagged[i][j];
}
}
}
public void DoMathProp(ArrayTest a)
{
int width = Width, height = Height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//this[i, j] *= a[i, j];
this[i, j] = this[i, j] * a[i, j];
}
}
}
public void DoMathFaster(ArrayTest a)
{
int width = Width, height = Height;
int[][] jagged = this.jagged,
_a = a.jagged;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//jagged[i][j] *= _a[i][j];
jagged[i][j] = jagged[i][j] * _a[i][j];
}
}
}
public void DoMathForeach(ArrayTest a)
{
int i = 0, j = 0;
foreach (var line in a.jagged)
{
j = 0;
foreach (var item in line)
{
//jagged[i][j] *= item;
jagged[i][j] = jagged[i][j] * item;
j++;
}
i++;
}
}
public void DoMathFastest(ArrayTest a)
{
int[][] _jagged = this.jagged,
_a = a.jagged;
int[] __jagged, __a;
for (int i = 0; i < _jagged.Length; i++)
{
__jagged = _jagged[i];
__a = _a[i];
for (int j = 0; j < __jagged.Length; j++)
{
//__jagged[j] *= __a[j];
__jagged[j] = __jagged[j] * __a[j];
}
}
}
public int Sum()
{
int sum = 15;
int[][] jagged = this.jagged;
for (int i = 0; i < jagged.Length; i++)
{
for (int j = 0; j < jagged[i].Length; j++)
{
sum = sum + jagged[i][j];
}
}
return sum;
}
public int SumProp()
{
int sum = 15;
int width = Width, height = Height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
sum = sum + this[i, j];
}
}
return sum;
}
public int SumForeach()
{
int sum = 15;
foreach (var line in jagged)
{
foreach (var item in line)
{
sum += item;
}
}
return sum;
}
public int SumFast()
{
int sum = 15;
int[][] jagged = this.jagged;
for (int i = 0; i < jagged.Length; i++)
{
int[] _jagged = jagged[i];
for (int j = 0; j < jagged[i].Length; j++)
{
sum += _jagged[j];
}
}
return sum;
}
}
class Program
{
static void Main(string[] args)
{
const int loop = 1000;
int width = 800, height = 800;
ArrayTest a1 = new ArrayTest(width, height),
a2 = new ArrayTest(width, height);
Stopwatch sw = new Stopwatch();
//DoMath
sw.Start();
for (int i = 0; i < loop; i++)
{
a1.DoMath(a2);
}
sw.Stop();
Console.WriteLine("DoMath: " + sw.ElapsedMilliseconds);
//DoMathProp
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.DoMathProp(a2);
}
sw.Stop();
Console.WriteLine("DoMathProp: " + sw.ElapsedMilliseconds);
//DoMathFaster
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.DoMathFaster(a2);
}
sw.Stop();
Console.WriteLine("DoMathFaster: " + sw.ElapsedMilliseconds);
//DoMathForeach
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.DoMathForeach(a2);
}
sw.Stop();
Console.WriteLine("DoMathForeach: " + sw.ElapsedMilliseconds);
//DoMathFastest
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.DoMathFastest(a2);
}
sw.Stop();
Console.WriteLine("DoMathFastest: " + sw.ElapsedMilliseconds);
//Sum
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.Sum();
}
sw.Stop();
Console.WriteLine("Sum: " + sw.ElapsedMilliseconds);
//SumProp
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.SumProp();
}
sw.Stop();
Console.WriteLine("SumProp: " + sw.ElapsedMilliseconds);
//SumForeach
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.SumForeach();
}
sw.Stop();
Console.WriteLine("SumForeach: " + sw.ElapsedMilliseconds);
//SumFast
sw.Restart();
for (int i = 0; i < loop; i++)
{
a1.SumFast();
}
sw.Stop();
Console.WriteLine("SumFast: " + sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
Run #1:
DoMath: 3931
DoMathProp: 3011
DoMathFaster: 3358
DoMathForeach: 3102
DoMathFastest: 1770
Sum: 729
SumProp: 745
SumForeach: 709
SumFast: 753
Run #2:
DoMath: 3945
DoMathProp: 2978
DoMathFaster: 3311
DoMathForeach: 3102
DoMathFastest: 1764
Sum: 730
SumProp: 744
SumForeach: 708
SumFast: 753
Run #3:
DoMath: 4041
DoMathProp: 2976
DoMathFaster: 3314
DoMathForeach: 3092
DoMathFastest: 1777
Sum: 732
SumProp: 748
SumForeach: 714
SumFast: 751
Run #1:
DoMath: 3045
DoMathProp: 2977
DoMathFaster: 2681
DoMathForeach: 3394
DoMathFastest: 1802
Sum: 738
SumProp: 753
SumForeach: 716
SumFast: 755
Run #2:
DoMath: 2966
DoMathProp: 2953
DoMathFaster: 2631
DoMathForeach: 3382
DoMathFastest: 1747
Sum: 734
SumProp: 738
SumForeach: 703
SumFast: 755
Run #3:
DoMath: 2965
DoMathProp: 2959
DoMathFaster: 2642
DoMathForeach: 3383
DoMathFastest: 1773
Sum: 729
SumProp: 747
SumForeach: 707
SumFast: 750
Run #1:
doMath: 1728.550504
doMathProp: 1747.916189
doMathFaster: 1736.039763
doMathForeach: 1734.981001
doMathFastest: 1732.675896
sum: 626.478196
sumProp: 627.959249
sumForeach: 629.493964
sumFast: 649.372465
Run #2:
doMath: 1791.048725
doMathProp: 1888.965311
doMathFaster: 1826.43116
doMathForeach: 1806.1341
doMathFastest: 1833.68291
sum: 772.088533
sumProp: 697.429715
sumForeach: 660.004415
sumFast: 756.06105
Run #3:
doMath: 1819.834545
doMathProp: 1821.309067
doMathFaster: 1809.052345
doMathForeach: 1719.76124
doMathFastest: 1719.466335
sum: 616.398258
sumProp: 627.816464
sumForeach: 650.758328
sumFast: 642.416087
__jagged = _jagged[i];
__a = _a[i];
public void DoMath(ArrayTest a)
{
int[][] arr = a.jagged;
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
jagged[i][j] *= arr[i][j];
}
}
}