$cache[$key] = empty($arr) ? NULL : $arr; return $cache[$key]; } // 门户 获取需要在频道显示的栏目主题数据 function portal_channel_thread($fid) { global $forumlist; if (empty($fid)) return NULL; $orderby = array('tid' => 1); $page = 1; // 遍历所有在频道显示内容的栏目 $category_forumlist = channel_category($fid); $arrlist = array(); $forum_tids = array(); $tidlist = array(); if ($category_forumlist) { foreach ($category_forumlist as &$_forum) { // 频道显示数据 $arrlist['list'][$_forum['fid']] = array( 'fid' => $_forum['fid'], 'name' => $_forum['name'], 'rank' => $_forum['rank'], 'type' => $_forum['type'], 'url' => $_forum['url'], 'channel_new' => $_forum['channel_new'], ); $forum_thread = thread_tid__find(array('fid' => $_forum['fid']), $orderby, $page, $_forum['channel_new'], 'tid', array('tid')); // 最新信息按栏目分组 foreach ($forum_thread as $key => $_thread) { $forum_tids[$key] = $_thread; } unset($forum_thread); } $tidlist += $forum_tids; } unset($category_forumlist); // 获取属性对应的tid集合 list($flaglist, $flagtids) = flag_thread_by_fid($fid); empty($flagtids) || $tidlist += $flagtids; unset($flagtids); // 频道置顶 $stickylist = sticky_list_thread($fid); empty($stickylist) || $tidlist += $stickylist; // 在这之前合并所有二维数组 tid值为键/array('tid值' => tid值) $tidarr = arrlist_values($tidlist, 'tid'); // 在这之前使用$tidarr = array_merge($tidarr, $arr)前合并所有一维数组 tid/array(1,2,3) if (empty($tidarr)) { $arrlist['list'] = isset($arrlist['list']) ? array_multisort_key($arrlist['list'], 'rank', FALSE, 'fid') : array(); return $arrlist; } $tidarr = array_unique($tidarr); $pagesize = count($tidarr); // 遍历获取的所有tid主题 $threadlist = well_thread_find_asc($tidarr, $pagesize); // 遍历时为升序,翻转为降序 $threadlist = array_reverse($threadlist); foreach ($threadlist as &$_thread) { // 各栏目最新内容 isset($forum_tids[$_thread['tid']]) AND $arrlist['list'][$_thread['fid']]['news'][$_thread['tid']] = $_thread; // 全站置顶内容 isset($stickylist[$_thread['tid']]) AND $arrlist['sticky'][$_thread['tid']] = $_thread; // 首页属性主题 if (!empty($flaglist)) { foreach ($flaglist as $key => $val) { if (isset($val['tids']) && in_array($_thread['tid'], $val['tids'])) { $arrlist['flaglist'][$key][array_search($_thread['tid'], $val['tids'])] = $_thread; ksort($arrlist['flaglist'][$key]); $arrlist['flag'][$_thread['tid']] = $_thread; } } } } unset($threadlist); if (isset($arrlist['sticky'])) { $i = 0; foreach ($arrlist['sticky'] as &$val) { ++$i; $val['i'] = $i; } } if (isset($arrlist['flag'])) { $i = 0; foreach ($arrlist['flag'] as &$val) { ++$i; $val['i'] = $i; } } if (isset($arrlist['flaglist'])) { foreach ($arrlist['flaglist'] as &$val) { $i = 0; foreach ($val as &$v) { ++$i; $v['i'] = $i; } } } isset($arrlist['list']) AND $arrlist['list'] = array_multisort_key($arrlist['list'], 'rank', FALSE, 'fid'); return $arrlist; } ?>performance - For Array, is it more efficient to use map() & reduce() instead of forEach() in javascript? - Stack Overfl
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

performance - For Array, is it more efficient to use map() & reduce() instead of forEach() in javascript? - Stack Overfl

programmeradmin0浏览0评论

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?

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?

Share Improve this question asked Jul 9, 2013 at 10:55 AndersonAnderson 2,7522 gold badges29 silver badges42 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 12

I just tested this today, using map and reduce over floating point numbers, with the latest node.js version, and the answer is that map and reduce was two orders of magnitude slower than an regular for loop.

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

~11,000ms

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

EDIT: One should note that this difference is much less in Firefox, and may be much less in future version of Node / Chrome as well.

1)

there's no side-effect with map() and reduce()

Well. You very well can implement map and reduce callbacks having side effects. Nothing prevents it and in the current state of JavaScript it's not even considered as bad practice.

2)

there's only 1 thread for js to execute on most of the browsers

There's only one thread in all today's JS engines, even when they run server-side (in fact there can be more but in isolation, not accessing the same array).

So the fact there is no side effect wouldn't make array modifications parallelisable at all. No JS engine can do otherwise than call the callback sequentially on standard arrays.

Note : as pointed by zirak, there's this not standard Mozilla ParallelArray thing which could help making parallel execution. I don't know if there's something similar on V8.

As long as the dimensions of the array are very low ( in order of 10's) then there is not much a difference in the performance, but when the size of the array increases to a very large value, then using conventional for loop is a great and better method, because we just need to loop through the elements and get a value at a specific index as we point, but in other methods, not only we are getting the value at an index, but also additional information such as the index, (in map, reduce, forEach) and accumulator value (in reduce). And these methods as need an a callback function, they both take up a great deal of stock on the memory for callbacks which further reduces the performance speed.

You can check the justification of this with the following script. Just see the values that are console logged.

 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));
});

It is easily overlooked, but the key to getting the benefits of MapReduce is to

A) Exploit the optimized shuffle. Often, your map and reduce functions can be implemented in a slow language, as long as the shuffle - the most expensive operation - is well optimized, it will still be fast and scalable.

B) Exploit the checkpointing functionality to recover from node failures (but hopefully, your CPU cores won't fail).

So in the end, map-reduce is actually neither about the map, nor the reduce functions. It's about the framework around it; which will give you good performance even with bad "map" and "reduce" functions (unless you lose control over your data set size in the shuffle step!).

The gains to be obtained from doing a multi-threaded map-reduce on a single node are fairly low, and most likely there are much better ways of parallelizing your shop for shared memory architectures than map-reduce...

Unfortunately, there is a lot of hype (and too little understanding) surrounding mapreduce these days. If you look up the original paper, it goes into detail about "Backup Tasks", "Machine Failures" and "locality optimization" (neither of which makes sense for an in-memory single-host use case).

Just because it has a "map" and a "reduce" doesn't make it a "mapreduce" yet.
It's only a MapReduce if it has an optimized shuffle, node crash and straggler recovery.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论