Search code examples
javascriptarraysobjectv8spread-syntax

V8 engine: why object spread at the start of new object create new hidden classes only after ninth element? Otherwise if spread at the end - its ok


I just read about hidden classes and inline caching. I found interesting performance thing, that break my mind.

So, we have the following code:

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);

if you run this on your computer you will see that the first map loop ran 5 times faster than the second.

I ran this snippet in the chrome console and got memory snapshot. As i could see, in first case i got new array(array1), where all objects have same hidden class (map). So this array.map loop ran fast. But in the second case, i got new array(array2) where only 9 first elements have the same Hidden Class which has back pointers to Hidden Class from origin array(array) elements. But other elements in the second array(array2) have unique Hidden Classes, which have no any back pointers. Also i noticed that access to object fields from array2 is slow.

So i think, that after first 9 elements V8 engine started to create slow-properties objects, but why?


Solution

  • Looks like a case where several optimizations are interfering with one another in a way that makes the end result less optimized than it should be. Reported at crbug.com/v8/13303.

    2023 Update: This issue is fixed in Chrome 117.