6

1)As we know, there's no side-effect with map() and reduce(). Nowadays, we also have muti-core on cell phone. So is it more efficient to use them?

2)On the other hand, there's only 1 thread for js to execute on most of the browsers. Therefor map() and reduce() are prepared for server-side scripting?

4

4 回答 4

10

我今天刚刚测试了这个,使用最新的 node.js 版本的浮点数使用 map 和 reduce,答案是 map 和 reduce 比常规 for 循环慢两个数量级。

var r = array.map(x => x*x).reduce( (total,num) => total+num,0);

~11,000 毫秒

var r = 0.0;
array.forEach( (x,i,a) => r += x*x  )

~300ms

var r = 0.0;
for (var j = 0; j < array.length;j++){
    var x = array[j];
    r += x*x;
}

~35ms

编辑:应该注意,这种差异在 Firefox 中要小得多,在未来版本的 Node / Chrome 中也可能要小得多。

于 2016-08-27T12:40:21.290 回答
3

1)

map() 和 reduce() 没有副作用

出色地。您可以很好地实现具有副作用的 map 和 reduce 回调。没有什么能阻止它,在 JavaScript 的当前状态下,它甚至不被认为是不好的做法。

2)

在大多数浏览器上只有 1 个 js 线程可以执行

今天所有的 JS 引擎中只有一个线程,即使它们在服务器端运行(实际上可以有更多,但隔离,不访问同一个数组)。

因此,没有副作用的事实根本不会使数组修改可并行化。除了在标准数组上按顺序调用回调之外,没有 JS 引擎可以做其他事情。

注意:正如zirak所指出的,这不是标准的 Mozilla ParallelArray东西,它可以帮助进行并行执行。不知道V8有没有类似的东西。

于 2013-07-09T10:58:10.627 回答
1

它很容易被忽视,但获得 MapReduce 好处的关键是

A)利用优化的 shuffle。通常,您的 map 和 reduce 函数可以用慢速语言实现,只要 shuffle(最昂贵的操作)得到很好的优化,它仍然是快速且可扩展的。

B) 利用检查点功能从节点故障中恢复(但希望您的 CPU 内核不会出现故障)。

所以说到底,map-reduce 实际上既不是 map,也不是 reduce 函数。这是关于它周围的框架;即使使用糟糕的“map”和“reduce”功能,它也会为您提供良好的性能(除非您在洗牌步骤中失去对数据集大小的控制!)。

在单个节点上执行多线程 map-reduce 所获得的收益相当低,并且很可能有比 map-reduce 更好的方法来并行化您的共享内存架构商店......

不幸的是,现在围绕 mapreduce 有很多炒作(而且理解太少)。如果您查看原始论文,它详细介绍了“备份任务”、“机器故障”和“局部优化”(这对于内存中的单主机用例都没有意义)。

仅仅因为它有一个“map”和一个“reduce”并不能使它成为一个“mapreduce”。
如果它具有优化的随机播放、节点崩溃和落后者恢复,则它只是一个 MapReduce。

于 2013-07-09T11:41:02.183 回答
1

只要数组的维度非常小(大约 10 的数量级),那么性能上没有太大的差异,但是当数组的大小增加到一个非常大的值时,使用常规的 for 循环是一个很好的选择更好的方法,因为我们只需要遍历元素并在我们指向的特定索引处获取值,但在其他方法中,我们不仅获取索引处的值,还获取索引等附加信息, (在 map、reduce、forEach 中)和累加器值(在 reduce 中)。而且这些方法都需要一个回调函数,它们都占用了大量的内存用于回调,进一步降低了性能速度。

您可以使用以下脚本检查其理由。只需查看控制台记录的值。

 var scripts=[];
// GLOBAL variales declaration
var a=[];
function preload() {
    for(var i=0;i<100000;i++) a[i]=i;
}
preload();
// TEST function 0
scripts.push(function() {
    var sum=0;
    a.forEach(function(v) {
        sum+=v;
    });
    //console.log(sum);
});
// TEST function 1
scripts.push(function() {
    a.reduce(function(acc,v) {
        return acc+v;
    });
});
// TEST function 2
scripts.push(function() {
    var sum=0;
    for(var i=0;i<a.length;i++) {
        sum+=a[i];
    }
});
// EVALUATION
scripts.forEach(function(f,index) {
    var date=new Date();
    for(var i=0;i<10000;i++) {
        f();
    }
    console.log("call "+index+" "+(new Date()-date));
});
于 2017-03-24T07:20:03.900 回答