JavaScriptでFREDDYデータを読み込む
低消費メモリを実現するには
SAXのような順方向のみのシリアルアクセス方式のツールで低消費メモリを実現するには、読み終わったデータをメモリ上から削除すれば良い。FREDDYはscriptタグを動的にDOMツリーへ挿入する手法でデータを読み込んでいるため、データの削除はDOMツリーから読み終わったPageを含むScriptタグを削除すれば良い(図3(上))。
ところが、JavaScriptのメモリ管理は完全にWebブラウザに依存している。しかも、Webブラウザは、DOMツリーから要素を削除したからと言って、その要素が利用していたメモリ空間を即座に削除するわけではないことが分かった。
図3(下)の左側のグラフを見てほしい。このグラフは、FREDDYでXML文書を読み込んでいる間の消費メモリ動向を示している。横軸がデータ読み込み開始からの時間、縦軸がその時点でのシステム全体のメモリ使用量を表している。グラフ中の黄色い線が、HTMLページのbody直下にscriptタグを追加し削除する手法を用いて消費メモリ量を計測した結果である。
グラフに表れているように、この手法によって消費されるメモリ量は、データの読み込みの進ちょくに従って右肩上がりとなっており、期待通りの動作とはなっていないことが見て取れる。なお、この計測はInternet Explorerで行った実験結果だが、Firefox 2でも同様の結果を得られた。ただし最新のFirefox 3に関しては、この問題は解消されているようである。
いくつかの実装手法を試した結果、この占有されたメモリ領域は、ページ遷移のタイミングで解放されることが分かった。そこでHTMLページの中にiframeタグを使ってそこに、FREDDYのPageを格納し、iframeのページ遷移を内部的に起こすことによってPageを切り替える手法を開発した。区別のため、body直下にscriptタグを加える実装をscript法、iframe内に加える手法をiframe法と呼ぶ。
最適な実装を目指して
iframe法で同じように、データ読み込み時のメモリ消費量を計測した。この計測結果をグラフ中に緑色の線で示している。iframe法では、メモリ消費量が一定となったが、読み込みにかかる時間がscript法よりも増加してしまった。この手法ではメモリ解放のためにiframeのsrc属性を更新することによって、内部的なページ遷移を起こし、FREDDYのPageを読み込んでいる。恐らく、この処理時間が上乗せされ、script法に比べて処理時間が増加したと考えられる。
これらの実装の知見から、現在のFREDDYでは、script法とiframe法を合わせた手法(ハイブリッド法と呼ぶ)を実装している。各実装法の概要を図3(下)の右側に示している。
ハイブリッド法では、iframe法と同じく、iframeタグを2つ用意している。そのiframeタグの内部にscript法と同じDynamic Script TagによってPageを読み込んでいる。そして一定数のPageを読み込んだ後、そのiframeを作成し直すことによって、内部的なページ遷移を起こし、イベントハンドラへ通知済みのPageが確保しているメモリ領域を解放する。
また、2つのiframeタグをダブルバッファとして利用することにより、データの読み込みとイベントの送信を効率良く行っている。この手法を使えば、一定の消費メモリ量で、あらゆるサイズのデータを読み込むことができ、またiframeの更新に伴うオーバヘッドも抑えることができる。ハイブリッド法での計測結果をグラフ中、青線で示す。
今回はFREDDYを使ったWebアプリケーションの実装手法と、FREDDYライブラリの内部実装について詳細に述べた。しかし、FREDDYの最大の利点は、記事の後半で述べたような実装の詳細をまったく理解せずとも、通常のSAXを利用するかのように簡単に実装できることである。冒頭で紹介したxml2freddy.phpを使えば、XMLファイルを与えるだけで、FREDDYのサンプルアプリケーションまで自動生成できる。後はそれを改造するだけで、利用者自身のFREDDYアプリケーションが作成できる。
さて、最終回となる次回は、FREDDYのアプリケーションと筆者らの研究の今後の展開について述べたいと思う。