创建Javascript数组的不同方法

时间:2016-05-31 23:20:47

标签: javascript arrays performance

我想了解构造数组的性能差异。运行以下程序,我对以下输出感到困惑:

Time for range0: 521
Time for range1: 149
Time for range2: 1848
Time for range3: 8411
Time for range4: 3487

我不明白为什么3需要超过4,而1需要短于2.而且,似乎地图功能效率很低;有什么用?

function range0(start, count) {
    var arr = [];
    for (var i = 0; i < count; i++) {
        arr.push(start + i);
    }
    return arr;
}

function range1(start, count) {
    var arr = new Array(count);
    for (var i = 0; i < count; i++) {
        arr[i] = start + i;
    }
    return arr;
}

function range2(start, count) {
    var arr = Array.apply(0, Array(count));
    for (var i = 0; i < count; i++) {
        arr[i] = start + i;
    }
    return arr;
}

function range3(start, count) {
    var arr = new Array(count);
    return arr.map(function(element, index) {
        return index + start;
    });
}

function range4(start, count) {
    var arr = Array.apply(0, Array(count));
    return arr.map(function(element, index) {
        return index + start;
    });
}

function profile(range) {
    var iterations = 100000,
        start = 0, count = 1000,
        startTime, endTime, finalTime;

    startTime = performance.now();

    for (var i = 0; i < iterations; ++i) {
        range(start, count);
    }

    endTime = performance.now();

    finalTime = (endTime - startTime);
    console.log(range.name + ': ' + finalTime + ' ms');
}

[range0, range1, range2, range3, range4].forEach(profile);

1 个答案:

答案 0 :(得分:1)

  

我不明白为什么3需要超过4

我也不是。这是一个令人惊讶的结果,鉴于我的肤浅分析和我通过分析代码获得的结果。在运行Google Chrome 50的计算机上,range4的速度是range3的两倍。

我必须研究您正在使用的Javascript实现,以便找出发生这种情况的原因。

  

而1小于2。

range1执行得更快,因为它使用循环并优化内存分配,而range2使用函数并执行不必要的内存分配。

  

另外,地图功能似乎非常低效;有什么用?

map函数用于根据现有值计算新的Array

[1, 2, 3, 4, 5].map(number => number * number);
// [1, 4, 9, 16, 25]

在我的电脑上

Time for range0: 783
Time for range1: 287
Time for range2: 10541
Time for range3: 14981
Time for range4: 28243

我的结果反映了我对每项功能表现的期望。

对每个函数的表面分析

  • range0

    创建Array并通过循环填充它。它是最简单直接的代码。我认为可以将其理解为基线以进行性能比较。

  • range1

    使用带有长度参数的Array constructor。这极大地优化了存储元素所需的底层内存分配。由于预先知道元素的确切数量,因此随着元素数量的增加,内存不必realloc;在实例化Array时,可以准确地分配存储所有元素所需的确切内存量。

  • range2

    Applies 参数列表到构造函数,this设置为数字0。这在语义上等同于Array() - 参数列表是使用count参数创建的,这与函数应用程序的结果无关。实际上,它不必要地浪费时间为参数列表分配内存。

    您可能打算使用call

    Array.call(null, count)
    
  • range3

    range1类似,但使用带有函数的map而不是循环。初始内存分配已经过优化,但调用函数count次的开销可能很大。

    此外,map会生成新的Array个实例。由于该实例也有count元素,因此优化 内存分配也是有意义的,但是我不清楚这是否真的发生了。然而,正在进行两次单独的内存分配,而不是range1中的一次。

  • range4

    结合range2range3的所有低效率。

    令人惊讶的是,它的执行速度比计算机上的range3快。我不明白为什么会发生这种情况。我想有人必须调查你的Javascript特定实现,以便弄明白。