假设你有一个二维数组int[][] a = new int[height][width],所以按照惯例你有索引a[y][x]。根据您表示数据的方式以及访问它们的方式,性能会以 20 倍的比例变化:
代码:
public class ObjectArrayPerformance {
public int width;
public int height;
public int m[];
public ObjectArrayPerformance(int w, int h) {
this.width = w;
this.height = h;
this.m = new int[w * h];
}
public int get(int x, int y) {
return this.m[y * width + x];
}
public void set(int x, int y, int value) {
this.m[y * width + x] = value;
}
public static void main (String[] args) {
int w = 1000, h = 2000, passes = 400;
int matrix[][] = new int[h][];
for (int i = 0; i < h; ++i) {
matrix[i] = new int[w];
}
long start;
long duration;
System.out.println("duration[ms]\tmethod");
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
matrix[y][x] = matrix[y][x] + 1;
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\t2D array, loop on x then y");
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
matrix[y][x] = matrix[y][x] + 1;
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\t2D array, loop on y then x");
//
ObjectArrayPerformance mt = new ObjectArrayPerformance(w, h);
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
mt.set(x, y, mt.get(x, y) + 1);
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\tmapped 1D array, access trough getter/setter");
//
ObjectArrayPerformance mt2 = new ObjectArrayPerformance(w, h);
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
mt2.m[y * w + x] = mt2.m[y * w + x] + 1;
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\tmapped 1D array, access through computed indexes, loop y then x");
ObjectArrayPerformance mt3 = new ObjectArrayPerformance(w, h);
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
mt3.m[y * w + x] = mt3.m[y * w + x] + 1;
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\tmapped 1D array, access through computed indexes, loop x then y");
ObjectArrayPerformance mt4 = new ObjectArrayPerformance(w, h);
start = System.currentTimeMillis();
for (int z = 0; z < passes; z++) {
for (int y = 0; y < h; y++) {
int yIndex = y * w;
for (int x = 0; x < w; x++) {
mt4.m[yIndex + x] = mt4.m[yIndex + x] + 1;
}
}
}
duration = System.currentTimeMillis() - start;
System.out.println(duration+"\tmapped 1D array, access through computed indexes, loop x then y, yIndex optimized");
}
}
我们可以得出结论,线性访问性能更多地取决于您处理数组的方式(行然后列还是相反?:性能增益 = x10,很大程度上归功于 CPU 缓存)而不是数组本身的结构(1D 与 2D : 性能增益 = x2)。
如果是随机访问,性能差异应该会小很多,因为 CPU 缓存的影响较小。