How does V8 optimise the creation of very large arrays?

谁说胖子不能爱 提交于 2021-02-18 15:06:13

问题


Recently, I had to work on optimising a task that involved the creation of really large arrays (~ 10⁸ elements).

I tested a few different methods, and, according to jsperf, the following option seemed to be the fastest.

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

Which was ~ 85% faster than

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

And indeed, the first snippet was much faster in my actual app as well.

However, my understanding was that the V8 engine was able to perform optimised operations on array with PACKED_SMI_ELEMENTS elements kind, as opposed to arrays of HOLEY_ELEMENTS.

So my question is the following:

  • if it's true that new Array(n) creates an array that's internally marked with HOLEY_ELEMENTS, (which I believe is true) and
  • if it's true that [] creates an array that's internally marked with PACKED_SMI_ELEMENTS (which I'm not too sure is true)

why is the first snippet faster than the second one?

Related questions I've been through:

  • Create a JavaScript array containing 1...N

  • Most efficient way to create a zero filled JavaScript array?


回答1:


V8 developer here. The first snippet is faster because new Array(max) informs V8 how big you want the array to be, so it can allocate an array of the right size immediately; whereas in the second snippet with []/.push(), the array starts at zero capacity and has to be grown several times, which includes copying its existing elements to a new backing store.

https://www.youtube.com/watch?v=m9cTaYI95Zc is a good presentation but probably should have made it clearer how small the performance difference between packed and holey elements is, and how little you should worry about it.

In short: whenever you know how big you need an array to be, it makes sense to use new Array(n) to preallocate it to that size. When you don't know in advance how large it's going to be in the end, then start with an empty array (using [] or new Array() or new Array(0), doesn't matter) and grow it as needed (using a.push(...) or a[a.length] = ..., doesn't matter).

Side note: your "for loop with new Array() and push" benchmark creates an array that's twice as big as you want.



来源:https://stackoverflow.com/questions/54481918/how-does-v8-optimise-the-creation-of-very-large-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!