富豪的にプログラミングに慣れきってるとJavaScript書いたときにたいへん困る

ということを経験した.普段Perlを使っているときは,速度とか効率の良いコードを書くよりも,きちんと動いて美しいコードを書くのが重要じゃんとか思ってたんだけど,そのままの感覚でJavaScript書いたらほんとに遅くてうごかないコードができてびっくらこいた.

具体的には,ツリーからDOMを作ってをたどるコードを書くのに,

  1. apiからツリーのデータを持ったJSONを読み込む
  2. JSONをもとにツリー構造を表現する自前クラスのインスタンスを作る
  3. 作ったインスタンスの持っているツリー構造をもとにDOMオブジェクトを生成する
  4. 再帰を使ったメソッドでDOMオブジェクトをたどる

みたいなことをしていて,それなりに綺麗なコードになってたんだけど,ツリーを何度もたどりすぎてたいへん遅かった.3000くらいのノードを持ったツリーを処理するのに,1回のリクエストあたり1分30秒とかかかる.

こんなんまったく使えないので,

  1. JSONから読み込むとか言う無駄なことせずにあらかじめHTMLとして埋め込んでおく.
  2. クラスにはツリー構造を持たせずにDOMのノードを保持するだけにする
  3. 不用意に再帰を使ってDOMをたどらずにに,可能なところではあるノード以下の全部のノードを取得するような手法を使う.

というように工夫してみた.無駄にJSONをevalしたり,クラスを時間をかけて作る必要がなくなったので,さすがに1分30秒とかではなく,何とか耐えれるスピードで動くようになった.

3をやるのには,prototype.jsで使えるselectメソッドを使って,

block.select('span').each( function (node) {
    //process
})

とかやると,この場合blockというノード以下のspanノードが取得できる.内部ではdocument.evaluateをつかっていて,XPathを使ってノードで取得できて便利.って,これがどれだけ速さに貢献しているかは謎ではある.

いろいろやったおかげでなったものの,ノードごとにクラスが使えないので各ノードの情報を保持するのに外部のハッシュを使ったりと,なにかと無理のある実装になってしまったなぁ.

うーん,ぐだぐだ書いてみたものの,3000くらいノードがあるツリーを何度もたどらないといけないアルゴリズムが一番悪いという説がどろり濃厚である.得られる結果は同じなわけで,すくなからず,JavaScriptは速度を気にしながらかかないとだめだわな.

直接ではないですが,第30回 JavaScriptの動作を軽くするための工夫が実に参考になりました.