V8:异构数组文字

V8: Heterogeneous Array Literals

我迷失在 V8 源代码以及有关该主题的文章中,我偶然发现了一个博客 post,其中指出:

If you are forced to fill up an array with heterogeneous elements, let V8 know early on by using an array literal especially with fixed-size small arrays.

let array = [77, 88, 0.5, true]; //V8 knows to not allocate multiple times.

如果这是真的,那么为什么是真的?为什么是数组字面量?与通过构造函数创建数组相比,这有什么特别之处?作为 V8 源代码的新手,很难找出 homogeneous/heterogeneous 数组的差异所在。

此外,如果回答者可以指出相关的 V8 源代码,我将不胜感激。

编辑:稍微澄清一下我的问题(数组文字与数组构造函数)

V8 开发人员blog post provided by Mathias

常见元素种类

While running JavaScript code, V8 keeps track of what kind of elements each array contains. This information allows V8 to optimize any operations on the array specifically for this type of element. For example, when you call reduce, map, or forEach on an array, V8 can optimize those operations based on what kind of elements the array contains.

以这个数组为例:

const array = [1, 2, 3];

What kinds of elements does it contain? If you’d ask the typeof operator, it would tell you the array contains numbers. At the language-level, that’s all you get: JavaScript doesn’t distinguish between integers, floats, and doubles — they’re all just numbers. However, at the engine level, we can make more precise distinctions. The elements kind for this array is PACKED_SMI_ELEMENTS. In V8, the term Smi refers to the particular format used to store small integers. (We’ll get to the PACKED part in a minute.)

稍后将浮点数添加到同一数组会将其转换为更通用的元素种类:

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
// elements kind: PACKED_DOUBLE_ELEMENTS
Adding a string literal to the array changes its elements kind once again.

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
// elements kind: PACKED_DOUBLE_ELEMENTS
array.push('x');
// elements kind: PACKED_ELEMENTS

.....

V8 为每个数组分配一个元素种类。 数组的元素种类不是一成不变的——它可以在 运行 时间改变。在前面的示例中,我们从 PACKED_SMI_ELEMENTS 转换为 PACKED_ELEMENTS。 元素种类转换只能从特定种类过渡到更一般的种类。

因此,在幕后,如果您在 运行 时不断向数组添加不同类型的数据,V8 引擎必须在幕后进行调整,从而失去默认优化。

就构造函数与数组字面量而言

如果您事先不知道所有值,请使用数组文字创建一个数组,然后将值推送给它:

const arr = [];
arr.push(10);

这种方法确保数组永远不会转换为多孔元素类型。因此,V8 可以更有效地优化数组上的任何未来操作。

此外,为了阐明 by holey

的含义

Creating holes in the array (i.e. making the array sparse) downgrades the elements kind to its “holey” variant. Once the array is marked as holey, it’s holey forever — even if it’s packed later!

可能还值得一提的是,V8 目前有 21 different element kinds

更多资源