Прежде чем мы узнаем, как улучшить производительность spread-оператора в JavaScript, заглянем под капот работы с итерированными объектами самого оператора.
Оператор spread, или многоточие, работает с массивами или вообще с итерированными объектами и разделяет их на элементы, из которых формируется новый массив.Таким образом, оператор ..., используемый перед массивом, или любой другой коллекцией значений (строки, объекты), называет spread.
Spread-оператор может стоять на любой позиции внутри литерала массива:
const numbers = [1, 2, 3];
[0, ...numbers]; // => [0, 1, 2, 3]
[0, ...numbers, 4]; // => [0, 1, 2, 3, 4]
[...numbers, 4]; // => [1, 2, 3, 4]
А теперь интересный вопрос: зависит производительность кода от расположения spread-оператора в массиве? Узнаем!
1. Создаем вспомогательные функции
Перед тем как начнем сравнения производительности, объявим две функции. Первая из них - appendToTail():
function appendToTail(item, array) {
return [...array, item];
}
const numbers = [1, 2, 3];
appendToTail(10, numbers); // => [1, 2, 3, 10]
Суть созданной функции в том, что она вставляет числа в конец массива. Для этого мы используем конструкцию [...array, item].
Следующая функция appendToHead():
function appendToHead(item, array) {
return [item, ...array];
}
const numbers = [1, 2, 3];
appendToHead(10, numbers); // => [10, 1, 2, 3]
appendToHead()- чистая функция, которая возвращает новый массив, где элементы добавляются в начало. Для этого используем конструкцию [item, ...array].
Вам может показаться, что нет никакой разницы в производительности этих функций. Но ...
2. Тест производительности
Протестуем скорость конструкций [...array, item]vs [item, ...array] на MacBook Pro в таких браузерах:
- Chrome 76
- Firefox 68
- Safari 12.1
Результаты проверки:
Видим, что в браузерах Firefox и Safari оба варианта имеют примерно одинаковую производительность.
А вот в Chrome конструкция [...array, item] отрабатывает вдвое быстрее, чем [item, ...array].
Поэтому, чтобы ускорить производительность spread-оператора в Chrome, используйте его в начале литерал массива:
const result = [...array, item];
Возникает вопрос: почему так происходит?
3. Fast-path оптимизация
Начиная с версии 7.2, двигатель V8, который отвечает за выполнение JavaScript в Chrome, поддерживает оптимизацию spread-оператора: fast-path оптимизацию .
Кратко поясним принцип ее работы.
Без оптимизации, когда двигатель наталкивается на оператор spread, вызывается метод итератора iterator.next() для итерированных объектов. На каждой итерации память конечного массива увеличивается и добавляется новый элемент.
Однако с fast-path оптимизацией мы избегаем создания объекта итератора вообще. Двигатель определяет длину расширенного массива и выделяет память только раз для конечного массива. Далее каждый элемент расширенного массива добавляется в конечный. Таким образом и увеличивается производительность.
4. Поддерживаемые структуры данных
Fast-path оптимизация применяется к таким структурам данных в JavaScript:
массивы
const numbers = [1, 2, 3, 4];
[...numbers, 5]; // => [1, 2, 3, 4, 5]
строки
const message = 'Hi';
[...message, '!']; // => ['H', 'i', '!']
сети
const colors = new Set(['blue', 'white']);
[...colors, 'green']; // => ['blue', 'white', 'green']
[...colors.values(), 'green']; // => ['blue', 'white', 'green']
[...colors.keys(), 'green']; // => ['blue', 'white', 'green']
Map
Поддерживается только для методов map.keys()и map.values():
const names = new Map([[5, 'five'], [7, 'seven']]);
[...names.values(), 'ten']; // => ['five', 'seven', 'ten']
[...names.keys(), 10]; // => [5, 7, 10]
Вывод
Когда мы используем оператор spread в начале массива, производительность кода увеличивается благодаря fast-path оптимизации. Она доступна в двигатели V8 с версии 7.2 (представлено в Chrome v72и NodeJS v12).
Тесты производительности показывают, что можно достичь двойного ускорения, если использовать конструкцию [...array, item], а не [item, ...array].
Конечно, fast-path - полезная вещь, однако стоит обращать на это внимание только при работе с большими массивами, когда производительность действительно очень важна.
0 комментариев
Добавить комментарий