functional style的代價

 Tue, 30 Nov 2010 23:59:05 +0800

之前在nodejs討論群回覆別人問題,使用了之前文章:用函數處理函數,來擴充函數原本的功能中,讓函數執行特定次數的方法,配合遞迴來解決問題。不過他的問題,其實把直接執行的程式改成函數就可以解了。

我比較好奇的是效能,所以把這兩種寫法拿來測試一下:

<html>
<body>
</body>
</html>
<script>
//global variables... easier for testing
var input = [],output=[];
var input1=[],output1=[];
//limit a function to run n times. will always return null while over the limit
function times(n, f) {
  var c=0;
  return function() {
    var args = [];
    for(var i=0,j=arguments.length; i<j; i++) {
      args.push(arguments[i]);
    }
    if(c<n) {
      c++;
      return f.apply(this, args);
    } else {
      return null;
    }
  };
}
//the core function for this test.
var work = function(res) {
  return res.shift();
};
//limit the 'work' function to run 10 times
var f1 = times(10, work);
//run recursively for test1
var r1 = function(res, f) {
  var ret = f(res);
  if(null !== ret) {
    output.push(ret);
    r1(res, f);
  }
};
//run iteratively n times for test2
var r2 = function(n) {
  for(var i=0; i<n; i++) {
    output1.push(work(input1));
  }
};
//test1: recursive version, initial global input and output variables then run r1
//the codes within test1 and test2 are almost identical
function test1() {
  input = [0,1,2,3,4,5,6,7,8,9];
  output = [];
  r1(input, f1);
}
//test2: iterative version, initial global input1 and output1 vairables then run r2
function test2() {
  input1 = [0,1,2,3,4,5,6,7,8,9];
  output1 = [];
  r2(10);
}
//run each test 100000 times to make the difference of the two tests visible
var count = 100000;
var d1 = new Date().getTime();
for(var i=0; i<count; i++) {
  test1();
}
var d2 = (new Date().getTime()) - d1;
var d3 = new Date().getTime();
for(var i=0; i<count; i++) {
  test2();
}
var d4 = (new Date().getTime()) - d3;
alert(d2);
alert(d4)
</script>

疑?結果用functional風格的寫法,速度竟然比簡單loop的寫法快了三倍左右(在Chrome8。在Opera差距更大,大約五到六倍,其他瀏覽器跟Chrome8差不多。)...我以為用loop會比較快說

嗯,所以...使用Javascript時,適當地搭配functional、recursive的寫法,並不會影響到效能,有時還會更快!


2010-12-10 19:47 補充:

最近跟噗友討論了一下這個問題:http://www.plurk.com/p/9gb24a,不過還是有點難確定為什麼速度的差距是這樣。