rhino VS WSH(JScript)
javascriptの継続渡しのコードをたまたま見つけて自分も試したくなって書いてみた。
// 普通のfibonacci function fib(n) { if((n==1) || (n==2)) return 1; else return fib(n-1) + fib(n-2); } // 継続渡し版fibonacci function fib_cps(n,k) { if((n==1) || (n==2)) return k(1); else return fib_cps(n-1, function(v1){ return fib_cps(n-2, function(v2){ return k(v1+v2); }); }); } //時刻測定用 function getSpentTime() { var d = new Date(); return function(){ puts("time:" + ((new Date()).getTime() - d.getTime()) + " ms"); return; } } function puts(str) { if(typeof(print) == "function") print(str); // rhino else WScript.Echo(str); // wsh } function test_cps(i) { var t = getSpentTime(); // 時刻計測開始 var n = fib_cps(i, function(val){return val;}); puts("fibonacci(" + i + ") =" + n); t(); // ここで経過時刻が表示される } test_cps(13);
このスクリプトはrhinoでも、WSHでも実行できるように書いてある。さて、どっちが早いの?
というわけで勝負させてみた。
結果:rhino
[Machine]@Owner$ java -jar js.jar fib_cps.js fibonacci(13) =233 time:121 ms
[Machine]@Owner$ CScript fib_cps.js Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. fibonacci(13) =233 time:20 ms
ぅぉぉぉぉお、WSHが速い!
余談:自分の環境ではどっちも、test_cps(14)でスタックオーバーフローになった。
WSHは素直にスタックオーバーフロー、と一言出して死ぬのだが、rhinoはすさまじく大暴れする。(スタックトレースがこれでもかと出続ける)
次に、fib_cpsじゃなくて、fibで試してみる。今度は少しスタックにも余裕が出るのでループにしてみた。
つまり、最後をこういうコードに変えてみた。
(前略) //test_cps(13); // コメントアウト function test(max) { var total = getSpentTime(); // ループ全体の計測 for(var i=1;i<max;i++){ var t = getSpentTime(); // 時刻計測開始 var n = fib(i); puts("fibonacci(" + i + ") =" + n); t(); // 表示 } puts("-----------\ntotal:"); total(); } test(30);
さて、結果はどうなるか。
結果:WSH
Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. fibonacci(1) =1 time:0 ms fibonacci(2) =1 time:0 ms fibonacci(3) =2 time:0 ms fibonacci(4) =3 time:0 ms fibonacci(5) =5 time:0 ms fibonacci(6) =8 time:0 ms fibonacci(7) =13 time:0 ms fibonacci(8) =21 time:10 ms fibonacci(9) =34 time:0 ms fibonacci(10) =55 time:0 ms fibonacci(11) =89 time:0 ms fibonacci(12) =144 time:0 ms fibonacci(13) =233 time:0 ms fibonacci(14) =377 time:0 ms fibonacci(15) =610 time:10 ms fibonacci(16) =987 time:10 ms fibonacci(17) =1597 time:10 ms fibonacci(18) =2584 time:30 ms fibonacci(19) =4181 time:40 ms fibonacci(20) =6765 time:60 ms fibonacci(21) =10946 time:101 ms fibonacci(22) =17711 time:150 ms fibonacci(23) =28657 time:250 ms fibonacci(24) =46368 time:401 ms fibonacci(25) =75025 time:671 ms fibonacci(26) =121393 time:1071 ms fibonacci(27) =196418 time:1753 ms fibonacci(28) =317811 time:2804 ms fibonacci(29) =514229 time:4546 ms ----------- total: time:11917 ms
26あたりから、最後は息切れしたかのように、明らかに遅くなる。これに対して、
結果:rhino
fibonacci(1) =1 time:10 ms fibonacci(2) =1 time:0 ms fibonacci(3) =2 time:0 ms fibonacci(4) =3 time:0 ms fibonacci(5) =5 time:0 ms fibonacci(6) =8 time:10 ms fibonacci(7) =13 time:0 ms fibonacci(8) =21 time:0 ms fibonacci(9) =34 time:0 ms fibonacci(10) =55 time:0 ms fibonacci(11) =89 time:0 ms fibonacci(12) =144 time:10 ms fibonacci(13) =233 time:20 ms fibonacci(14) =377 time:10 ms fibonacci(15) =610 time:10 ms fibonacci(16) =987 time:0 ms fibonacci(17) =1597 time:0 ms fibonacci(18) =2584 time:10 ms fibonacci(19) =4181 time:0 ms fibonacci(20) =6765 time:10 ms fibonacci(21) =10946 time:20 ms fibonacci(22) =17711 time:30 ms fibonacci(23) =28657 time:40 ms fibonacci(24) =46368 time:70 ms fibonacci(25) =75025 time:110 ms fibonacci(26) =121393 time:191 ms fibonacci(27) =196418 time:280 ms fibonacci(28) =317811 time:471 ms fibonacci(29) =514229 time:731 ms ----------- total: time:2033 ms
結果は、rhinoの圧勝となった。
jvmの起動の時間も含まれるため、短いとrhinoは分が悪い。
しかし、一度起動してしまえば、どういう理屈かわからないが、rhinoのほうが神のように速くなる。
(少なくとも、私の環境では)
すごいぜ!rhino!
おまけ:
環境。
動作環境:Intel PentiumM 900MHz / Memory 512MB
rhinoは、今日付けで取れる最新のを使った。rhino1_6R7.zip(jvmは1.4.0_01とやや古い)
WSHはXPに標準で付いてくる5.6
おまけ2:
ふと、Dateの実装の違いが実は不公平なのかな?
と、思って、Dateを取り除いてtimeコマンドで試したりしてみたが、やっぱり、変わらなかった。