読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

AJAXサイトの定期観測向け性能計測ツールを作ってみた

AJAXサイトの定期観測向け性能計測ツールを作ってみましたよ。

  • ページの読み込み時間、サーバーAPIの呼び出し時間ならJMeterJavaScriptの実行時間ならBenchmark.jsで計測できるけど、
  • これらをひっくるめた読み込みを開始してから画面に情報が表示されるまでにかかる一連の時間を計測するツールとなるとFireBugくらいしか見当らないなー・・・。
  • FireBugでも計測はできるけど、計測対象ページがいっぱいあったり、5回計測して平均をとる、とかいう場合にはちょいシンドイ。
  • FireBug自体のオーバーヘッドも若干気になるし・・。
  • あと、IE7,8でも測らんといかんので、同じ仕組みでIEでもFireFoxでも計測できるようにしておきたい。

というのが経緯。「ログ出力監視方式」の計測ツールならこれらの要件を満たせそう && 割とさくっと作れそうじゃね?と思い立って作ってみました。

仕組みと機能

  • 計測対象のサイトをインラインフレーム内に読み込んで、あらかじめ仕込んでおいたログが出力されるまでの時間を計測するという仕組みです。
    • ○ページの読み込み時間から、サーバーAPIの呼び出し時間、JavaScriptの実行時間を含めた読み込みを開始してから画面に情報が表示されるまでにかかる一連の時間を計測できます。
    • 特定のブラウザに依存しませんIEFirefoxそれぞれの計測を同じツールで行えます。(原理的には)
    • ×計測対象ページにあらかじめログ出力コードを埋めておく必要があります。
    • ×iframeへのロードが禁止されていると計測できません。
      • iframeへのロード禁止コードを計測時にはoffにするなどの対処が必要になります・・・。
      • あと、クロスドメインだといろいろ制限に引っかかるかも。任意のサイトを測るツール、というよりは開発中のプロジェクトに組み込んで使う感じを想定してます。
  • 計測対象のページや計測内容は、JavaScripで定義する方式です。
    • 複数のテストを定義しておいて、まとめて実行できます。
  • 指定された回数実行して平均、最大、最小を表示する機能もご用意。
      • まぁ、必要ですよね。

プロファイラ的な使い方も無理すればできますが、それはFireBugIEデバッグツールを使ったほうが便利。

  • そこそこページの多いサイトを作っていて、
  • 各ページの表示性能を定期的に一括計測できるようにしておきたい!

という場合向きです。

デモ

デモはこちら

  • 左上の「テストを実行」をクリックするとテストが開始されます。
  • 一通りテストが完了すると、右のパネルに結果が表示されるハズ。

ダウンロード

ファイル数が若干多いので、Google Codeに置いてます。
perfjs - Download

使い方

概要は以下。

  1. プロジェクトに計測ツール一式を取り込む
  2. 計測対象ページにログを埋め込む
  3. テストスクリプトを書く
  4. index.html にアクセス
1.プロジェクトに計測ツール一式を取り込む

ダウンロードしたzipに含まれるフィルのうち、以下をプロジェクトに取り込みます。

  • html/**
  • css/**
  • lib/**

配置場所は、HTTPで公開される場所であればどこでもOKです。

2.計測対象ページにログを埋め込む。

次に、計測対象とするページにログを埋め込みます。

  1. lib/perf-logger.jsにロガーの実装があるので、計測対象ページでこれを読み込んで、
  2. 「perf.logger.executed("<イベントID>");」を計測ポイントに入れていきます。
// ログを出力。
perf.logger.executed("test"); 
//  "test-<NO>"を記録。
//  <NO>はイベントの識別用番号で、イベントごとに1から順に採番されます。

// 一定の期間を計測するユーティリティもあります。 
var end = perf.logger.start("test"); // "start-test-<NO>"を記録。
setTimeout( function() {
  end(); // "end-test-<NO>"を記録
}, 1000);

「perf.logger.*」はデフォルトでは何も実行しない空関数なので、実行しても何も起こりません。ページがiframeに読み込まれた際に、ツールによって上書きされます。

3.テストスクリプトを書く

ログを仕込んだら、次にテストスクリプトを用意します。「samples/script.js」にサンプルがあるので参考に。

// テスト定義 
// 「../samples/test1.html」 を読み込んでdocument.onloadが呼ばれるまでの時間を計測する簡単なもの。
perf.regist({
  // テストの識別用ID
  id : "test1", 
  // 計測対象とする一連の処理。これの開始と終了までの所要時間が計測されます。
  test: [
    // 「../samples/test1.html」を読み込む。
    perf.ops.load( "../samples/test1.html" ), 
    // 「loaded-1」が出力されるまで待機する。
    // 「loaded」イベントは出力コードを書かなくても、document.onloadのタイミンクで自動で記録されます。
    perf.ops.wait( perf.exps.logged( "loaded-1" )) 
  ]
});
// 「../samples/test3.html」を読み込んで、ページで定義されているグローバル関数「log」を実行し、処理が完了するまでを計測するサンプル。
perf.regist({
  id : "test3. サイトの関数を実行",
  // 前準備として実行する一連の処理。
  // testと違ってこちらの所要時間は計測範囲に含まれません。
  // また、後始末としてteardownも定義できます。
  setup: [
     perf.ops.load( "../samples/test3.html" ), // 「../samples/test3.html」を読み込み
     perf.ops.wait( perf.exps.logged( "loaded-1" )) // 読み込み完了を待つ
  ],
  test: [
    // 「../samples/test3.html」のグローバル関数「log」x3を実行。
    perf.ops.call( function( global ) {
      global.log( "a" ); 
      setTimeout( function(){
        global.log( "b" ); 
      }, 200);
      setTimeout( function(){
         global.log( "c" ); 
      }, 500);
    }),
    // グローバル関数「log」の処理完了を示すログがすべて出力されるのを待機する。
    perf.ops.wait( perf.exps.all(
      perf.exps.logged( "end-a-1" ),
      perf.exps.logged( "end-b-1" ),
      perf.exps.logged( "end-c-1" )
    ))
  ]
});

作成が完了したら、「./html/index.html」でスクリプトをロードする設定を行ってください。

... (略)
<script type="text/javascript" src="../samples/scripts.js"></script>
4. index.html にアクセス。

あとは、アプリケーションサーバーなりWebサーバーなりを起動して、「./html/index.html」にアクセスすればOK。

・・・

やや突貫工事だったりするのでUIとかいろいろショボイですが・・・。とりあえずこれでストップウォッチは回避できるかな。