【问题标题】:Why it takes Longer to make smaller array?为什么制作更小的阵列需要更长的时间?
【发布时间】:2017-08-09 16:40:14
【问题描述】:

这是从1 to n 创建数组的函数:

 function MakeList(n){
       return Array.from(Array(n).keys()).map(function(x){return x+1;});
    }

我计时了,所以我可以找到最快的方法来制作这个数组:

console.log(n);
console.time("MakeList");
var ar = MakeList(n);
console.timeEnd("MakeList");

但是输出太奇怪了!:

1
MakeList: 0.897ms
2
MakeList: 0.135ms
5
MakeList: 0.048ms

为什么制作长度为 1 的数组要比 5 长约 20 倍?

任何关于最快方式的建议将不胜感激!

【问题讨论】:

  • 您可能正在预热您的 JIT 或其他东西。尝试以随机顺序进行,并使用大量迭代。仅使用 1 次迭代将几乎完全受噪声支配。
  • 仅供参考,您不需要.map()。你可以这样做:let d = Array.from(Array(n + 1).keys()); d.shift(); return d;
  • 仅供参考,一个简单的 for 循环初始化器在 Chrome 中似乎快 40 倍:jsperf.com/create-array-sequence/1 for n = 5
  • 而且,当您在时序循环中针对您的确切功能进行多次迭代进行适当的性能测试时,它们确实会按预期顺序完成:Chrome、Firefox 和 Edge 中的jsperf.com/makelist/1

标签: arrays node.js performance performance-testing


【解决方案1】:

一个简短的函数调用本身的时间非常短,以至于解释器中发生的其他事情(启动 JIT、编译或优化一些代码、分配一些内存)的微小变化可能会产生影响您记录的时间。为了解决这个问题,大多数性能测试会运行数千次迭代,并对整个迭代块进行计时,以使一次迭代中的微小变化变得无关紧要。例如,如果您的函数在 jsperf 中的值为 1、2、5 和 10,每个函数执行数千次迭代,那么您将在 Chrome、Firefox 和 Edge 中获得预期的完成顺序。以下是 Chrome 的数字(数字越大速度越快):

 makeList(1)    2,470,356 ops/sec
 makeList(2)    1,861,029 ops/sec
 makeList(5)      992,583 ops/sec
 makeList(10)     626,572 ops/sec

您可以在this jsperf 的您最喜欢的浏览器中自行运行。


由于您对速度感兴趣,因此您可以立即进行一项改进并通过更改此代码来消除 .map()

return Array.from(Array(n).keys()).map(function(x){return x+1;});

到这里:

let d = Array.from(Array(n + 1).keys()); 
d.shift(); 
return d;

这会在原始数组上创建一个额外的数组条目,然后删除第零个条目以获得一个从 1 开始的数组,而不是像您之前那样重新创建一个全新的数组。


而且,一个普通的 for 循环初始化器在 Chrome 中似乎快 40 倍,如 this jsperf 所示:

function makeList2(n) {
    let d = new Array(n);
    for (let i = 1; i <= n; i++) {
        d[i-1] = i;
    }
    return d;
}

【讨论】:

  • @veto - 这能回答你的问题吗?如果是这样,您可以通过单击答案左侧的绿色复选标记向社区表明这一点,这也将为您赢得一些声誉积分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多