性能計測インターセプタ
ありがちですが、メソッドの呼び出しにかかった時間を表示するインターセプタを書いてみました。せっかくなのでDIコンテナに登録して使えるようにしています。
機能
- メソッドの開始前と開始後の時刻を取得し、ミリ秒単位で呼び出しにかかった時間を得る。
- 時刻は「new Date().getTime()」で取得しているため、精度はDateクラスのそれに準ずる。
- 5回試行し、平均と最大、最小を表示。
実装とサンプル
var stdout = document.getElementById("stdout"); /** * メソッドの実行時間を計るインターセプタ * メソッドを5回実行して、平均、最大、最小を表示する。 * * @param {Object} mi container.MethodInvocation */ function pref( mi ) { var count = 5; // 試行回数 var total = 0; var max = null; var min = null; for ( var i = 0; i < count; i++ ) { var start = new Date(); try { mi.proceed(); } finally { var time = new Date().getTime() - start.getTime(); total += time; if ( !max || max < time ) { max = time; } if ( !min || min > time ) { min = time; } } } stdout.innerHTML += mi.getMethodName() + " :avg " + Math.floor((total / count)) + "ms, max " + max + "ms, min " + min + "ms,<br/>" ; } // 以下はサンプルです。 -------- // 計測対象 function Logic( ) {} Logic.prototype = { // インクリメントでループ a: function() { var x = ""; for ( var i = 0; i < 20000; i++ ) { x += "a"; } }, // デクリメントでループ b: function() { var x = ""; for ( var i = 20000; i >= 0; i-- ) { x += "a"; } } } // コンテナの初期化 var c = new container.Container( function( binder ) { binder.bind( "logic" ).to( Logic ); // 性能計測インターセプタをグローバルインターセプタとして設定 binder.bindInterceptor( pref, container.any(), container.any()); }); // メソッドを呼び出し。処理時間が表示される。 var logic = c.get("logic"); logic.a(); logic.b();
グローバルインターセプタとして登録したので、コンテナ上のすべてのコンポーネントのメソッド呼び出しで、実行時間が表示されます。
どうでもいいけど
Javaだとデクリメントでループした方が早い、とか言う話をだいぶ前に聞いた気がしますが、JavaScriptだとあまり変わらないみたいですね。(Javaの方もだいぶ前の話なので、最近はどうか知りませんが。)あと、IE6はかなり重かったけど、+=のせいかも。