为什么Array.from的回调比map函数慢很多?

Why is Array.from's callback much slower than the map function?

今天做一些性能测试的时候发现Array.from's callback work pretty slower than running the 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 函数。 polyfill 的代码看起来也很相似。知道为什么性能会有如此差异吗?

在 Google Chrome 74.0.3729.157、macOS

中测试

不是映射函数慢,Array.from调用本身

如果我们删除所有不必要的变量和条件语句,我们将得到以下简化的基准,returns:

Chrome74:

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

火狐 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.fromArray.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');