循环慢于减少?

时间:2018-11-21 17:08:28

标签: javascript performance reduce benchmarking

这段代码给我带来了非常奇怪的时机。有时for循环的运行要慢得多。

var len = 8e6

function *rands(){
  for(let i =0; i < len; i++)
    yield Math.random()
}

var add = (a,b) => a + b
var arr = new Float64Array([...rands()])


console.time('reduce')
var sum = arr.reduce(add)
console.log(sum)
console.timeEnd('reduce')

console.time('loop')
var sum = 0
for(let i = 0; i < len; i++)
  sum += arr[i]
console.log(sum)
console.timeEnd('loop')

1 个答案:

答案 0 :(得分:1)

在第一个示例中,您为V8编译器提供了有关类型是什么的提示,因此不必担心装箱/拆箱。

此处for循环的略微修改版本。 在我的机器上,for循环现在比reduce快5倍。

var len = 8e6

function *rands(){
  for(let i =0; i < len; i++)
    yield Math.random()
}

var add = (a,b) => a + b
var arr = new Float64Array([...rands()])


console.time('reduce')
var sum = arr.reduce(add)
console.log(sum)
console.timeEnd('reduce')

console.time('loop')
var sum = new Float64Array([0]);
for(var i = 0; i < len; i++)
  sum[0] += arr[i];
console.log(sum[0])
console.timeEnd('loop')

您可以看到sum[0] += arr[i];,现在V8编译器很容易知道此计算使用Float64进行添加,因为左右两侧都必须是Float64。

当您使用-> sum += arr[i]时,V8的右侧知道它是Float64,但是左侧可以是任何东西,它可以是整数,字符串甚至是Float64,因此V8必须检查如果需要将其装箱到Float64中。

使用reduce时,再次隐含了add函数的左侧和右侧将是Float64,因为v8引擎正在遍历Float64的数组,它知道的a和b将是Float64。