为什么第二个操作比第一个操作快?

时间:2019-04-30 15:13:42

标签: javascript node.js ecmascript-6

我试图查看for和reduce在数值数组之间的性能差异,并且我可以看到总是我正在测量的第二个函数(无论是for还是reduce)更快比第一。我猜想这与使用节点的数据缓存或线程池大小有关。这是代码:

process.env.UV_THREADPOOL_SIZE = 1;

let array = [
  1,
  23,
  4,
  5,
  6,
  7,
  8,
  7,
  65,
  4,
  3,
  23,
  43,
  2,
  23,
  32,
  23,
  23,
  234,
  243,
  423,
  432,
  43,
  23,
  2,
  23,
  2,
  23,
];

let sum = 0;
console.time('reduce');
sum = array.reduce((s, p) => (s += p), 0);
console.timeEnd('reduce');

sum = 0;
console.time('for');
for (let i = 0; i < array.length; i++) {
  sum += array[i];
}
console.timeEnd('for');

此代码显示了不同的结果:

process.env.UV_THREADPOOL_SIZE = 1;

let array = [
  1,
  23,
  4,
  5,
  6,
  7,
  8,
  7,
  65,
  4,
  3,
  23,
  43,
  2,
  23,
  32,
  23,
  23,
  234,
  243,
  423,
  432,
  43,
  23,
  2,
  23,
  2,
  23,
];

let sum = 0;
console.time('for');
for (let i = 0; i < array.length; i++) {
  sum += array[i];
}
console.timeEnd('for');

sum = 0;
console.time('reduce');
sum = array.reduce((s, p) => (s += p), 0);
console.timeEnd('reduce');

我的意思是,如果您颠倒执行顺序,则测量结果将有所不同。

要进行测试,我正在使用节点v11.11.0

有什么想法吗?

编辑:我不是在寻找解释为什么为什么reduce快于for或类似的东西。我想知道为什么nodejs在这种操作序列中产生这种结果。

5 个答案:

答案 0 :(得分:2)

  

我的意思是,如果您颠倒执行顺序,则测量结果将有所不同。

这意味着:您的测试存在某种缺陷,或者结果是如此随机,以致您无法基于它们做出判断。

更频繁地运行测试(几千次),然后花费平均时间(通过该时间来平均化其他代码段的影响(您正在多线程计算机上运行),然后迫使引擎选择它最强大的优化)。

在此之前,无法判断其中之一是否更快。结果很可能是:没关系,两者都足够快。

值得一读: Which is faster? - Eric Lippert

答案 1 :(得分:1)

经过测试,两者之间没有很大的时间差。

在链接中,您可以通过修改执行次数对其进行测试。

https://repl.it/@statefull/TrustworthyDefiniteArraylist

经过一些测试,问题出在console.time函数上。

看到这个:

https://repl.it/@statefull/WrathfulCostlyIrc

第一次调用console.time会花费更多时间。每次执行时都会将其与Date.now进行比较。

更多测试表明,直到第一个console.timeEnd的时间测量才是真实的。

请参阅: https://repl.it/@statefull/SoggyLimegreenUser

答案 2 :(得分:0)

您为reduce的每次迭代将一个函数添加到堆栈中(() => {}是一个新的函数调用)。这些函数调用会增加整个过程的额外时间。

只要时间限制不是很严格或数组很大,提高可读性通常是值得的。

答案 3 :(得分:0)

这是脚本或JIT编译语言中的常见现象,与编译器的开销减慢了操作速度有关,但这只是第一次。第一次之后,您将调用已编译的代码,而不是编译脚本,尽管这取决于执行引擎的实现方式。这就是为什么测试通常要求您一次执行一次而不是几次(数千次,理想情况下)的原因

答案 4 :(得分:-2)

Map / Reduce / Filter / Find很慢,因为它们具有回调函数,这些函数会增加开销