简体   繁体   English

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

[英]Is flattening JavaScript 2D arrays worth any performance gain?

As far as I know, there are two main ways of storing 2D data. 据我所知,存储2D数据有两种主要方式。 One, a 2D array: 一,二维数组:

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

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

The other, a flat array with a stored width : 另一个是具有存储width的平面阵列:

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

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

It's being said all over the Internet that "multidimensional" arrays are bad and perform super poorly compared to flat arrays and storing the width. 互联网上有人说,“多维”阵列很糟糕,与平面阵列和存储宽度相比表现得非常糟糕。 (Also, typed arrays can be used to speed up the second variant even more). (此外,类型化数组可用于加速第二种变体)。 However, I really dislike the syntax you must use to access a point with the flat array, and I think that you should code as close to what you mean. 但是,我真的不喜欢使用平面数组访问点必须使用的语法,我认为你应该编写尽可能接近你的意思。 Also, it's a lot of (I think) unnecessary math every frame. 而且,每帧都有很多(我认为)不必要的数学。

I'm in a situation where I need to handle large 2D arrays quickly (you guessed it, a game) and I want to know if flattening my arrays is worth the possible performance gain. 我正处于需要快速处理大型2D阵列的情况下(你猜对了,一个游戏)我想知道扁平化我的阵列是否值得获得可能的性能。 So, is it? 那么,是吗?

1D array may have a performance benefit due to the index look-up times. 由于索引查找时间,1D阵列可能具有性能优势。 A 2D+ array will first have to have one index looked up, then in the resulting array yet another and so forth. 2D +数组首先必须查找一个索引,然后在结果数组中查找另一个索引,依此类推。 There is an initial cost each time but it may be microscopic all in all. 每次都有一个初始成本,但总的来说可能是微观的。

If you really want a gain in performance then consider using Typed Arrays . 如果您真的希望获得性能提升,那么请考虑使用Typed Arrays These are actual low-level byte arrays and you can use them with 8-bit, 16-bit, 32-bit and 32/64 bits float values, signed and unsigned (latter not for float). 这些是实际的低级字节数组,您可以将它们与8位,16位,32位和32/64位浮点值一起使用,有符号和无符号(后者不用于浮点数)。

If your numbers are of one type then you can use typed arrays. 如果您的数字是一种类型,那么您可以使用类型化数组。 You use them as any other array with index look-up but performance can be many times as these are optimized by the JS engine(s): 您可以将它们用作具有索引查找的任何其他数组,但性能可以多次,因为这些是由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.

I think I've found an ideal solution to my own problem! 我想我找到了解决自己问题的理想方案! Here is a benchmark . 这是一个基准

UPDATE : The originial benchmark was incorrect and the updated version shows that flat typed arrays perform just slightly better than 2D typed arrays. 更新 :原始基准测试不正确,更新版本显示平面类型阵列的性能略好于2D类型阵列。

2D arrays turned out to be much slower than the flattened version, just as everyone warns. 正如每个人都警告的那样,2D阵列比扁平版本慢得多。 However, if the second level is a Typed Array, then it performs better than a flat array (even if the flattened one is typed as well) . 但是,如果第二级是一个Typed Array,那么它的表现 要比一个平面数组好(即使也输入了扁平数组) Thanks to @Ken for pointing me to typed arrays. 感谢@Ken将我指向了类型化数组。

This will allow me to code how I think ( array[x][y] ), while also having superior performance. 这将允许我编写我的想法( array[x][y] ),同时还具有卓越的性能。

I created some jsperf tests for 1000x1000 arrays (larger than the OP used in their jsperf), and added methods for returning a single nested array / flat array slice. 我为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];
}

For getting and setting, Chrome 60 has pretty much the same speed for the 2 methods, and in EdgeHTML 15 the nested array is ~ 50% quicker. 对于获取和设置,Chrome 60与2种方法的速度几乎相同,而在EdgeHTML 15中,嵌套数组的速度提高了约50%。

But most importantly, for getting the nested arrays / slicing, the nested array is much, much quicker. 但最重要的是,为了获得嵌套数组/切片,嵌套数组要快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM