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,不過還是有點難確定為什麼速度的差距是這樣。