小编典典
通常,在搜索答案时,最好的办法是查看如何将选择编译到JVM字节码中:
multi = new int[50][50];
single = new int[2500];
这被翻译成:
BIPUSH 50
BIPUSH 50
MULTIANEWARRAY int[][] 2
ASTORE 1
SIPUSH 2500
NEWARRAY T_INT
ASTORE 2
因此,如您所见,JVM已经知道我们在谈论多维数组。
进一步说明:
for (int i = 0; i < 50; ++i)
for (int j = 0; j < 50; ++j)
{
multi[i][j] = 20;
single[i*50+j] = 20;
}
这被转换为(跳过循环):
ALOAD 1: multi
ILOAD 3: i
AALOAD
ILOAD 4: j
BIPUSH 20
IASTORE
ALOAD 2: single
ILOAD 3: i
BIPUSH 50
IMUL
ILOAD 4: j
IADD
BIPUSH 20
IASTORE
因此,如您所见,多维数组在VM内部进行处理,无用指令不会产生开销,而单条指令会使用更多指令,因为偏移是手动计算的。
我认为性能不会成为问题。
编辑:
我做了一些简单的基准测试,看看这里发生了什么。我选择尝试不同的示例:线性读取,线性写入和随机访问。时间以毫秒表示(并使用进行计算System.nanoTime()。结果如下:
线性写入
尺寸:100x100(10000) 多:5.786591
单身:6.131748
尺寸:200x200(40000) 多:1.216366
单身:0.782041
尺寸:500x500(250000) 多:7.177029
单身:3.667017
尺寸:1000x1000(1000000) 多:30.508131
单身:18.064592
尺寸:2000x2000(4000000) 多:185.3548
单身:155.590313
尺寸:5000x5000(25000000) 多:955.5299
单身:923.264417
尺寸:10000x10000(100000000) 多:4084.798753
单身:4015.448829
线性读取
尺寸:100x100(10000) 多:5.241338
单身:5.135957
尺寸:200x200(40000) 多:0.080209
单身:0.044371
尺寸:500x500(250000) 多:0.088742
单身:0.084476
尺寸:1000x1000(1000000) 多:0.232095
单身:0.167671
尺寸:2000x2000(4000000) 多:0.481683
单身:0.33321
尺寸:5000x5000(25000000) 多:1.222339
单身:0.828118
尺寸:10000x10000(100000000) 多:2.496302
单身:1.650691
随机读取
尺寸:100x100(10000) 多:22.317393
单身:8.546134
尺寸:200x200(40000) 多:32.287669
单身:11.022383
尺寸:500x500(250000) 多:189.542751
单身:68.181343
尺寸:1000x1000(1000000) 多:1124.78609
单身:272.235584
尺寸:2000x2000(4000000) 多:6814.477101
单身:1091.998395
尺寸:5000x5000(25000000) 多:50051.306239
单身:7028.422262
随机数有点误导,因为它为多维数组生成2个随机数,而为一维数组生成一个随机数(并且PNRG可能会消耗一些CPU)。
请记住,我试图通过在同一循环的第20次运行之后进行基准测试来使JIT正常工作。为了完整起见,我的Java VM是以下内容:
Java版本“ 1.6.0_17” Java SE运行时环境(内部版本1.6.0_17-b04)Java
HotSpot(TM)64位服务器VM(内部版本14.3-b01,混合模式)
2020-09-11