Как V8 оптимизирует создание очень больших массивов? - PullRequest
0 голосов
/ 01 февраля 2019

Недавно мне пришлось работать над оптимизацией задачи, которая включала создание действительно больших массивов (~ 10⁸ элементов).

Я протестировал несколько разных методов , и, согласно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 мог выполнять оптимизированные операции над массивом с элементами типа PACKED_SMI_ELEMENTS, в отличие от массивов HOLEY_ELEMENTS.

Итак, мой вопрос заключается в следующем:

  • , если верно, что new Array(n) создает массив, который внутренне помечен HOLEY_ELEMENTS (что, я считаю, верно) и
  • если это правда, что [] создает массив, который внутренне помечен PACKED_SMI_ELEMENTS (что я не слишком уверен, верно)

почему первый фрагмент быстрее, чем второйодин?

Смежные вопросы Я был черезh:

1 Ответ

0 голосов
/ 01 февраля 2019

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 for с новым Array () и push "создает массив, который в два раза больше, чемты хочешь.

...