将项目推入数组的最佳性能方法?

The best performant way to push items into array?

在我的网站上,我有很多包含数据的数组。 例如:顶点数组、颜色数组、尺寸数组...

我正在处理大量项目。高达数千万。

在将数据添加到数组之前,我需要对其进行处理。 直到现在,我都是在主线程中完成的,这让我的网站冻结了 X 秒。 由于处理以及将处理后的数据添加到数组中,它冻结了。

今天我'moved'(做了很多工作)处理成web workers,但是处理后的数据是在主线程中添加的。我设法节省了处理的冻结时间,但没有节省添加的时间。

添加只​​需 array.push()array.splice() 即可。

我读过一些关于数组如何工作的文章,发现当我们将项目添加到数组时,数组被完全复制到内存中的一个新位置,大小为 array.length + 1 并在那里添加价值。这使我的数据推送缓慢。

我还了解到类型化数组要快得多。但是为此我需要知道数组的大小,我不知道,并且创建一个带有额外计数器的大类型数组并管理在中间(而不是数组的末尾)添加项目将是一个很多代码更改,我现在不想这样做。

所以,对于我的问题, 我有来自 Web Worker 的 return TypedArray,我需要将其放入常规数组中。最好的性能方法是什么? (今天我 运行 一个接一个地循环)

编辑

网站工作原理示例: 客户添加项目数,比如说 100000。 正在收集项目原始数据并将其发送给工作人员。 工作人员正在处理所有信息并将处理后的数据作为类型化数组发回(用作可传输对象)。在主线程中,我们将处理后的数据添加到数组中——添加到末尾或某个特定的索引中。 第二轮。客户再添加 100000 个项目。发送给工作人员并将结果添加到主线程数组。 第 3 轮可以是 10 个项目,第 4 轮 10000,第 5 轮可以删除索引 10-2000,...

使用评论进行了更多研究并考虑了另一个方向。

我尝试过使用 typedArray.set 方法,发现它非常非常快。

1000 万个项目使用集合花费了 0.004 秒,相比之下 array.push 0.866 秒。我将 1000 万分成 10 个数组,只是为了确保 set 方法在从索引 0 开始时不会工作得更快。

这样我想我什至可以使用 TypedArray 实现我自己的 insertAtIndex,它将所有项目向前推进并在正确的索引中设置新的 one\s。

此外,我可以使用 TypedArray.subArray 根据数组中的实际数据量(这不是复制数据)来获取我的子数据 - 对于将数据上传到缓冲区很有用(WebGL )

我说我想使用常规数组,但我认为这种性能提升不会有其他好处。当我将 MyNewTypedArray 包装为带有所有 pushsplice、自己的实现的 TypedArray 时,它并没有那么多工作。

希望此信息对大家有所帮助

var maxCount = 10000000;
var a = new Float32Array(maxCount);
var aSimple = [];

var arrays = [];
var div = 10;
var arrayLen = maxCount / div;
for (var arraysIdx = 0; arraysIdx < div; arraysIdx++) {
  var b = new Float32Array(arrayLen);
  for (var i = 0; i < b.length; i++) {
    b[i] = i * (arraysIdx + 1);
  }
  arrays.push(b);
}

var timeBefore = new Date().getTime();

for (var currArrayIdx = 0; currArrayIdx < arrays.length; currArrayIdx++) {
  a.set(arrays[currArrayIdx], currArrayIdx * arrayLen);
}
var timeAfter = new Date().getTime();
good.innerHTML = (timeAfter - timeBefore) / 1000 + " sec.\n";
timeBefore = new Date().getTime();
for (var currArrayIdx = 0; currArrayIdx < arrays.length; currArrayIdx++) {
  for (var i = 0; i < arrayLen; i++) {
    aSimple.push(arrays[currArrayIdx][i]);
  }
}

timeAfter = new Date().getTime();
bad.innerHTML = (timeAfter - timeBefore) / 1000 + " sec.\n";
Using set of TypedArray:
<div id='good' style='background-color:lightGreen'>working...</div>
Using push of Array:
<div id='bad' style='background-color:red'>working...</div>