Вопрос о алокации JS массивов: #array #perf #v8 #opti
Насколько я помню в си мы аллоцирум палять для массива и каждый раз когда мы хотим увеличить число элементов в массиве, мы должны сделать вновь аллоцировать память. Имеет ли смысл делать тоже самое на js? var arr = [1, 2, 3];, я хочу добавить ещё два элемента в массив, arr.length= 5; arr[3] = 4; arr[4] = 5; и будет ли это влиять на производительность? И что делать если всётаки нудно увеличить длину массива.
Я расширю ответ на все множество ситуаций для подобной темы.
Ответ [Часть 1/4]:
В JavaScript, в случае вопросов о том, что работает быстрее всегда нужно помнить две вещи:
1. Как это закреплено в спецификации
2. Как это оптимизирует конкретный #RunTime
* Если явно не указано другого, то рекомендации идут для RunTime: #V8.
Справка:
V8 - это RunTime от Google. Который встраивается сейчас в Google Chrome и NodeJs. Так же является одним из самых популярных RunTime для встраивания в разного рода штуки для Умного Дома - типа чайников, холодильников и т.д.
Я не знаю на момент написания ответа, иного RunTime, который бы по совокупности факторов, мог бы конкурировать с V8.
Под совокупностью факторов подразумевается: Базовая производительность, производительность в случае оптимизации горячего кода. Простота интеграции RunTime в другие HOST системы.
Как это закреплено в спецификации
Именно для Exotic Object Array, то есть того обьекта который мы создаем при помощи конструктора #
Потому каждый RunTime крутится как хочется.
В случае V8, для exotic object Array используется следующая стратегия:
Внутри RunTime существует 20 вариантов представления подобного обьекта.
Производительность которых сильно отличается друг от друга.
V8 устроен таким образом, что при создании Exotic Object Array, он получает наиболее производительную форму, которая в последствии деградирует до менее производительной, опираясь на те данные которые используются в Array.
Самое быстрое представление:
Например использование значений:
Насколько я помню в си мы аллоцирум палять для массива и каждый раз когда мы хотим увеличить число элементов в массиве, мы должны сделать вновь аллоцировать память. Имеет ли смысл делать тоже самое на js? var arr = [1, 2, 3];, я хочу добавить ещё два элемента в массив, arr.length= 5; arr[3] = 4; arr[4] = 5; и будет ли это влиять на производительность? И что делать если всётаки нудно увеличить длину массива.
Я расширю ответ на все множество ситуаций для подобной темы.
Ответ [Часть 1/4]:
В JavaScript, в случае вопросов о том, что работает быстрее всегда нужно помнить две вещи:
1. Как это закреплено в спецификации
2. Как это оптимизирует конкретный #RunTime
* Если явно не указано другого, то рекомендации идут для RunTime: #V8.
Справка:
V8 - это RunTime от Google. Который встраивается сейчас в Google Chrome и NodeJs. Так же является одним из самых популярных RunTime для встраивания в разного рода штуки для Умного Дома - типа чайников, холодильников и т.д.
Я не знаю на момент написания ответа, иного RunTime, который бы по совокупности факторов, мог бы конкурировать с V8.
Под совокупностью факторов подразумевается: Базовая производительность, производительность в случае оптимизации горячего кода. Простота интеграции RunTime в другие HOST системы.
Как это закреплено в спецификации
Именно для Exotic Object Array, то есть того обьекта который мы создаем при помощи конструктора #
Array
или литеральной формы []
никакого особого поведения, для оптимизации работы, с точки зрения спецификации - не предусмотрено. Потому каждый RunTime крутится как хочется.
В случае V8, для exotic object Array используется следующая стратегия:
Внутри RunTime существует 20 вариантов представления подобного обьекта.
Производительность которых сильно отличается друг от друга.
V8 устроен таким образом, что при создании Exotic Object Array, он получает наиболее производительную форму, которая в последствии деградирует до менее производительной, опираясь на те данные которые используются в Array.
Самое быстрое представление:
var theArr = [1, 3, 2];или
var theArr = new Array (1, 3, 2);Такое представление называется
PACKED_SMI_ELEMENTS
.[1] PACKED
: в обьекте (нет и не было) дырок [2] SMI:
элементы состоят из целых чисел со знаком в пределе 2^(32-1
). То есть в пределе между -1073741824 до 1073741823
. 2^31 степени: 0-2147483647
однако V8 по умолчанию оперирует SMI со знаком, в следсndии чего еще один бит уходит на знак.[3] ELEMENTS
: Значения связаны с числовыми ключами. (0, 1, 2, .... )
Любое превышение заявленого предела для SMI, приводит к преобразованию Exotic Object Array к другой форме, которая называется PACKED_DOUBLE_ELEMENTS
.Например использование значений:
1073741824, NaN, -0, 1.1 etc...
То есть форме, которая хранит в себе 64-bit IEEE floating point number❤4👍1