是否可以将JavaScript 2D数组展平,从而获得任何性能提升

时间:2014-02-25 04:33:26

标签: javascript arrays performance multidimensional-array

据我所知,存储2D数据有两种主要方式。一个是2D阵列:

var array = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// access element at (1, 1)
array[1][1];

另一个是一个存储有width的平面数组:

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var width = 3;

// access element at (1, 1)
array[1 * width + 1];

互联网上有人说“多维”阵列很糟糕,与平面阵列和存储宽度相比表现得非常糟糕。 (此外,类型化数组可用于加速第二种变体)。但是,我真的不喜欢使用平面数组访问点必须使用的语法,我认为你应该编写尽可能接近你的意思。此外,每帧都有很多(我认为)不必要的数学。

我正处于需要快速处理大型2D阵列的情况下(你猜对了,一个游戏)我想知道展平我的阵列是否值得获得可能的性能提升。那么,是吗?

3 个答案:

答案 0 :(得分:6)

由于索引查找时间,1D阵列可能具有性能优势。 2D +数组首先必须查找一个索引,然后在结果数组中查找另一个索引,依此类推。每次都有一个初始成本,但它可能都是微观的。

如果您真的希望获得性能提升,请考虑使用 Typed Arrays 。这些是实际的低级字节数组,您可以将它们与8位,16位,32位和32/64位浮点值一起使用,有符号和无符号(后者不用于浮点数)。

如果您的数字是一种类型,那么您可以使用类型化数组。您可以将它们用作具有索引查找的任何其他数组,但性能可以是多次,因为这些是由JS引擎优化的:

var array = new Uint8Array(9);  // 9 x bit-width, here 8 = 9 bytes

// write
array[0] = 1;
array[1] = 2;
...etc.

// read
var value1 = array[0];
...etc.

答案 1 :(得分:3)

我想我找到了解决自己问题的理想方案!这是benchmark

更新:原始基准测试不正确,更新版本显示平面类型数组的性能略好于2D类型数组。

正如每个人都警告的那样,2D阵列比扁平版本慢得多。但是,如果第二级是一个Typed Array,那么它执行的比一个平面数组更好(即使也是类型化的)感谢@Ken将我指向了类型化数组。

这将允许我编码我的想法(array[x][y]),同时也具有卓越的性能。

答案 2 :(得分:0)

我为1000x1000阵列创建了一些jsperf测试(大于其jsperf中使用的OP),并添加了返回单个嵌套数组/平面数组切片的方法。

var arrDim = 1000;


var clArr = new Array(arrDim);
for (var i = 0; i < arrDim; i++) {
    clArr[i] = new Uint8Array(arrDim);
}

clArr.getSlice = function(i) {
    return this[i];
}
clArr.setVal = function(i, j, val) {
    this[i][j] = val;
}
clArr.getVal = function(i, j) {
    return this[i][j];
}


var flArr = new Uint8Array(Math.pow(arrDim, 2));

flArr.getSlice = function(i) {
    var start = i*arrDim;
    return this.slice(start, start + arrDim);
}
flArr.setVal = function(i, j, val) {
    this[i*arrDim + j] = val;
}
flArr.getVal = function(i, j) {
    return this[i*arrDim + j];
}

对于获取和设置,Chrome 60与2种方法的速度几乎相同,而在EdgeHTML 15中,嵌套数组的速度提高了约50%。

但最重要的是,为了获得嵌套数组/切片,嵌套数组要快得多。