V8如何优化超大型阵列的创建?

时间:2019-02-01 14:54:39

标签: javascript arrays performance v8

最近,我不得不优化一个涉及创建非常大的数组(〜10个元素)的任务。

我测试了few different methods,据jsperf称,以下选项似乎是最快的。

var max = 10000000;
var arr = new Array(max);
for (let i = 0; i < max; i++) {
  arr[i] = true;
}

比那快〜85%

var max = 10000000;
var arr = [];
for (let i = 0; i < max; i++) {
  arr.push(true);
}

实际上,第一个代码片段在我的实际应用中也要快得多。

但是,我的理解是,与PACKED_SMI_ELEMENTS数组相反,具有HOLEY_ELEMENTS个元素的数组上的V8 engine was able to perform optimised operations类型。

所以我的问题如下:

  • 如果确实是new Array(n)创建了一个内部标记有HOLEY_ELEMENTS(我相信是真的)和
  • 的数组
  • 如果确实是[]创建了一个内部标记有PACKED_SMI_ELEMENTS的数组(我不太确定是真的)

为什么第一个代码片段比第二个要快?

我经历过的相关问题:

1 个答案:

答案 0 :(得分:5)

V8开发人员在这里。第一个代码段更快,因为new Array(max)告知V8您希望数组的大小,因此它可以立即分配大小合适的数组;而在第二个带有[] / .push()的代码段中,该数组从零容量开始,并且必须增长多次,这包括将其现有元素复制到新的后备存储中。

https://www.youtube.com/watch?v=m9cTaYI95Zc是一个很好的演示,但可能应该更清楚地说明填充元素和有孔元素之间的性能差异有多小,您应该为此担心的程度很少。

简而言之:只要您知道需要多大的数组,就可以使用new Array(n)将其预分配给该大小。当您不知道最终要有多大时,然后从一个空数组开始(使用[]new Array()new Array(0) ,无关紧要)并根据需要进行扩展(使用a.push(...)a[a.length] = ...无关紧要)。

旁注:“使用new Array()和push进行for循环”基准测试创建的数组要大两倍。