V8 如何优化超大数组的创建?
How does V8 optimise the creation of very large arrays?
最近,我不得不优化一项涉及创建非常大的数组(~ 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);
}
事实上,第一个片段在我的实际应用中也快得多。
但是,我的理解是 V8 engine was able to perform optimised operations 数组 PACKED_SMI_ELEMENTS
元素种类,而不是 HOLEY_ELEMENTS
.
数组
所以我的问题如下:
- 如果
new Array(n)
确实创建了一个内部标记为 HOLEY_ELEMENTS
的数组(我相信这是真的)和
- 如果
[]
确实创建了一个内部标记为 PACKED_SMI_ELEMENTS
的数组(我不太确定这是真的)
为什么第一个片段比第二个片段快?
我遇到的相关问题:
Create a JavaScript array containing 1...N
Most efficient way to create a zero filled JavaScript array?
这里是 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] = ...
,无关紧要)。
旁注:您的 "for loop with new Array() and push" 基准创建的数组是您想要的两倍大。
最近,我不得不优化一项涉及创建非常大的数组(~ 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);
}
事实上,第一个片段在我的实际应用中也快得多。
但是,我的理解是 V8 engine was able to perform optimised operations 数组 PACKED_SMI_ELEMENTS
元素种类,而不是 HOLEY_ELEMENTS
.
所以我的问题如下:
- 如果
new Array(n)
确实创建了一个内部标记为HOLEY_ELEMENTS
的数组(我相信这是真的)和 - 如果
[]
确实创建了一个内部标记为PACKED_SMI_ELEMENTS
的数组(我不太确定这是真的)
为什么第一个片段比第二个片段快?
我遇到的相关问题:
Create a JavaScript array containing 1...N
Most efficient way to create a zero filled JavaScript array?
这里是 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] = ...
,无关紧要)。
旁注:您的 "for loop with new Array() and push" 基准创建的数组是您想要的两倍大。