V8引擎:为什么对象在新对象开始时扩展,仅在第九个元素之后创建新的隐藏类?否则,如果在最后传播 - 没关系

问题描述 投票:0回答:2

我刚刚读到有关隐藏类和内联缓存的内容。我发现了有趣的表演,这让我心碎。

所以,我们有以下代码:

const n = 100000;
const array = [];

for (let i = 0; i < n; i++) {
  array.push({ a: '2', b: '3', c: '4', d: '5' });
}

const date1 = Date.now();
const array1 = array.map(i => ({ someNewField1: 'test1', someNewField2: 'test2', ...i }))
console.log('first map: ', Date.now() - date1);

const date2 = Date.now();
const array2 = array.map(i => ({ ...i, someNewField: 'test1', someNewField2: 'test2', }))
console.log('second map:', Date.now() - date2);

如果您在计算机上运行此程序,您会发现第一个地图循环的运行速度比第二个快 5 倍。

我在 Chrome 控制台中运行了这段代码并获得了内存快照。正如我所看到的,在第一种情况下,我得到了新的数组(array1),其中所有对象都具有相同的隐藏类(映射)。所以这个 array.map 循环运行得很快。但在第二种情况下,我得到了新数组(array2),其中只有 9 个第一个元素具有相同的隐藏类,该隐藏类具有从原始数组(数组)元素指向隐藏类的反向指针。但第二个数组(array2)中的其他元素具有独特的隐藏类,它们没有任何后向指针。我还注意到从 array2 访问对象字段很慢。

所以我认为,在前 9 个元素之后,V8 引擎开始创建慢属性对象,但为什么?

javascript arrays object v8 spread-syntax
2个回答
2
投票

看起来像是多种优化相互干扰的情况,导致最终结果的优化程度低于应有的程度。报告于 crbug.com/v8/13303

2023 年更新:此问题已在 Chrome 117 中修复


1
投票

TurboFan(V8 优化编译器)对 Ignition(V8 解释器)生成的字节码执行多项“推测性优化”。 这些优化基于 TurboFan 对您的代码所做的几个假设。如果这些假设在运行时不成立,V8 必须执行一些

去优化

并返回到 Ignition 生成的原始、性能较差的字节码。 您可以尝试使用此工具来检查是否发生任何去优化:

https://github.com/andrewiggins/v8-deopt-viewer

© www.soinside.com 2019 - 2024. All rights reserved.