这段代码给我带来了非常奇怪的时机。有时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')
答案 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。