据我所知,存储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阵列的情况下(你猜对了,一个游戏)我想知道展平我的阵列是否值得获得可能的性能提升。那么,是吗?
答案 0 :(得分:6)
如果您真的希望获得性能提升,请考虑使用 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,那么它执行的这将允许我编码我的想法(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%。
但最重要的是,为了获得嵌套数组/切片,嵌套数组要快得多。