2007年05月19日

Javascript:replace へ関数を渡すと非常に遅くなる事がある

replace メソッドの色々な使い方を紹介した記事を幾つか見つけたんですが、これって場合によっては想定外な結果になるんじゃないかな。
該当場所を見つける度に関数のオーバーヘッドが掛かる訳ですから、テスト文字列によってパフォーマンスが著しく変わるハズではないかと。

以下参考に致しました。
「escapeHTML の実装 3 パターン (ベンチマーク付き)」
http://d.hatena.ne.jp/reinyannyan/20060711/
「激しく誤差の範囲内の予感」
http://d.hatena.ne.jp/f99aq/20060714/

ということでやってみた結果、それほど置換数が多くなくても ie に限ると10倍以上の差がでるようです。ff と op は有意義な差が無いです。

告白すると、replace で正規表現使ったり、関数を渡したりする事ができるなんて・・・。知りませんでした。

おいおい大丈夫かよってなもんで。
「問題なければすべて良し」的な対応をしてきた自分に激しく反省。これからもポロポロ垢が出てくるんだろーなぁ。

以下。テスト内容



 テスト


対象文字列はおよそ 3k。置換文字数は各々 110 個程度です。
テストはこちら

firefox だと途中でうっざいダイアログが出ますので、何回か試行が要るかも。

結果

ie7.0
multi replace: 63
single replace: 1000

ie6.0
multi replace: 47:
single replace: 812:

ff1.5
multi replace: 2250
single replace: 2500

op8.53
multi replace: 2750
single replace: 2141

ns7.1
multi replace: 203
single replace: 1000

なんで?ってな結果です。ns の結果が大体予想していた感じに近かったんですが、ie の速さは異常だし op に至っては関数を与えた方が速くなってる。
いままで op は色んなところで意外な結果を出してましたんで、おそらくパフォーマンスを上げる何らかの処理がなされているんだろうとは思いますが、今回はあまり成果が出ていません。ie のが圧倒的。

 テスト用コード


var regex = new RegExp('[&"<>]', "g");
var escapeRules = {"&" : "&amp;", '"' : "&quot;", "<" : "&lt;", ">" : "&gt;"};

// 単純に列挙
function escapeHTML_replace_multi(s) {
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

// 関数を渡してやる(キャッシュ付)
function escapeHTML_replace_func_rulescached(s) {
  return s.replace(regex, function(c){
    return escapeRules[c];
  });
}

// テスター
(function() {
  function test(f) {
    var tm = (new Date()).getTime();
    for(var i = 0; i < 100; i++){
      f(str);
    }
    return ((new Date()).getTime() - tm) + ":" + "<br>";
  }
  document.write("multi replace: ", test(escapeHTML_replace_multi));
  document.write("single replace: ", test(escapeHTML_replace_func_rulescached));
  document.write("multi replace: ", test(escapeHTML_replace_multi));
  document.write("single replace: ", test(escapeHTML_replace_func_rulescached));
  document.write("multi replace: ", test(escapeHTML_replace_multi));
  document.write("single replace: ", test(escapeHTML_replace_func_rulescached));
})();


うーん。問題ないよなぁ。結果が意外すぎる・・・。
テスト用の文字列 (str)は、テストを参照ください。
posted by HiFa at 11:08 | 🌁 | Comment(0) | TrackBack(0) | JavaScript雑感 | このブログの読者になる | 更新情報をチェックする
>>> スパムコメントは消してますよん。 お互い無駄な労力は避けましょう。 <<<

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/42220697
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。