Почему обратный вызов Array.from намного медленнее, чем функция map? - PullRequest
1 голос
/ 21 мая 2019

Сегодня, выполняя некоторые тесты производительности, я обнаружил, что функция обратного вызова Array.from работает намного медленнее, чем функция Array.map независимо.

Тесты были выполнены на массиве длиной 32000000 элементов следующим образом.

let t1;
const arr = Array.from(new Array(32000000), (v,i) => {
    if (i === 0) t1 = performance.now();
    return i;
});
let t2 = performance.now();

t2 - t1; // ~4500ms


let arr2 = Array.from(new Array(32000000));
arr2 = arr2.map((v,i) => {
    if (i === 0) t1 = performance.now();
    return i;
});
t2 = performance.now();

t2 - t1; // ~500ms

Я всегда думал, что Array.from просто запускает функцию map для себя при создании массива.Код полифилов тоже выглядит одинаково.Есть идеи, почему такая разница в производительности?

Протестировано в Google Chrome 74.0.3729.157, macOS

1 Ответ

1 голос
/ 21 мая 2019

Это не функция отображения, которая медленная, , это сам вызов Array.from .

Если мы удалим все ненужные переменные и условные операторы, мы получим следующий упрощенный тест, который возвращает:

Chrome 74:

Array.from with map: 4735.970ms
Array.map: 166.405ms
Array.map with from: 5101.585ms
Array.from: 4999.910ms

Firefox 67:


Array.from with map: 729.000ms
Array.map: 41.000ms
Array.map with from: 1150.000ms
Array.from: 619.000ms

Итак, мы можем видеть, что отображение на самом деле почти не занимает времени, все, что занимает большую часть времени, - это вызов Array.from.

Я предполагаю, что Array.from намного медленнее для выделения памяти и создания нового массива, чем тот, который возвращается Array.map только потому, что он гораздо более общий и сложный, чем функция map. Просто сравните их спецификации: Array.prototype.map vs Array.from , Array.from, кажется, намного сложнее оптимизировать компилятор для.

const arr = new Array(32000000);

console.time('Array.from with map');
const arr1 = Array.from(arr, (v,i) => {
    return i;
});
console.timeEnd('Array.from with map');


console.time('Array.map');
const arr2 = arr.map((v,i) => {
    return i;
});
console.timeEnd('Array.map');



console.time('Array.map with from');
const arr3 = Array.from(arr).map((v,i) => {
    return i;
});
console.timeEnd('Array.map with from');

console.time('Array.from');
const arr4 = Array.from(arr);
console.timeEnd('Array.from');
...