アドオン版 AutoPagerize のメモリリークに関する調査

Firefox4 用アドオンの AutoPagerize がメモリリークしているという話があった。

アドオン版の AutoPagerize を使うとメモリが大量に使用されるが、 代わりに Greasemonkey 版を使ったところメモリの使用量が減った、 なので Greasemonkey 版を使った方が良さそう、という意見が多い。

メモリリークの検証

http://lufesu.blog3.fc2.com/blog-entry-54.html などでアドオン版の AutoPagerize はメモリリークしてると書いてあるのだけれど、 他に入れてる拡張が挙げられていなかったり、 新規にプロファイル作ったのかどうかが謎だったりで、 検証が雑だなと感じたので調査した。

なお検証には Firefox 4.0.1 (Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1)を用いた。

検証方法

準備:

  1. https://bitbucket.org/xKairouan/apmemleaktest のスクリプトと適当な画像 (http://blog-imgs-44-origin.fc2.com/d/a/n/danboruparty/20110424005.jpg など)を同じディレクトリに入れる
  2. https://bitbucket.org/xKairouan/apmemleaktest のスクリプトを python apmemleaktest.py 100 として実行

検証:

  1. Firefox を プロファイルを指定して起動
  2. about:memory を開く
  3. 別のタブで http://localhost:8080/ を開く
  4. AutoPagerize が 100 ページまで読み込んで停止するまでスクロールする
  5. 30秒待つ
  6. about:memory を更新して memory in use を記録
  7. http://localhost:8080/ を開いていたタブを閉じる
  8. 3 に戻る
  9. 3-8 を 5 回実行した後に Firefox を閉じる

以上を検証用の各プロファイルについて行った。

検証に使用した各プロファイルは以下の通り。

  • profile-A: 新しく作成したプロファイルにアドオン版 AutoPagerize 0.7.2 をいれ、ページの読み込み間隔を早くするためにプロファイル中にある extensions/jid0-tKjnEA5X3eBoP5HnqjBYQ4U3AcM@jetpack/resources/jid0-tkjnea5x3ebop5hnqjbyq4u3acm-autopagerize-data/autopagerize.user.js の MIN_REQUEST_INTERVAL を 1 に変更したもの
  • profile-B: 新しく作成したプロファイルに Greasemonkey 0.9.3 と AutoPagerize for Greasemonkey 0.0.58 をいれたもの

実行した結果の memory in use の値は以下のようになった。

profile-A:

  • 1回目: 68,454,936
  • 2回目: 79,872,508
  • 3回目: 89,678,316
  • 4回目: 99,641,002
  • 5回目: 109,578,684

profile-B:

  • 1回目: 86,942,136
  • 2回目: 53,991,244
  • 3回目: 85,488,772
  • 4回目: 86,714,816
  • 5回目: 85,739,944

Greasemonkey 版の AutoPagerize を使用した方 (profile-B) では memory in use の値が 85 MB 付近で安定している (ただ 2 回目が memory in use が極端に減っているのはよくわからない。とりあえずメモリリークとは関係なさそう) のに対して、 アドオン版の AutoPagerize を使用した方 (profile-A) では 1回の実行ごとに memory in use の値が 10MB ほど増加している。 この結果からアドオン版の AutoPagerize はメモリリークしており、 Greasemonkey 版よりもメモリを多く使用してしまうことがわかる。

メモリリークの原因

アドオン版も Greasemonkey 版も、ページの継ぎ足しなどの AutoPagerize のコアの機能はだいたい同じスクリプトを使用している。 なのでアドオン版のみ メモリリークしているとすれば Jetpack 側の問題ではないかと思い、 Jetpack Add-on SDK のバグレポートを調べたところ次のような報告があった。 https://bugzilla.mozilla.org/show_bug.cgi?id=607601

これによると Jetpack が提供する page-mod モジュールを使ったアドオンではメモリリークが発生する、ということだった。 そしてアドオン版の AutoPagerize は このpage-mod モジュールを使用してページの継ぎ足し等を処理している (https://github.com/swdyh/autopagerize_for_firefox/blob/master/lib/main.js)。 なのでこの page-mod モジュールのバグがアドオン版 AutoPagerize のメモリリークの原因だと考えられる。

この page-mod モジュールのメモリリークは Add-on SDK 1.0b5 で既に修正されている。 2011-05-14 現在配布されているアドオン版の AutoPagerize 0.7.2 は Add-on SDK 1.0b3 でビルドされている (これはプロファイル中の extensions/jid0-tKjnEA5X3eBoP5HnqjBYQ4U3AcM@jetpack/harness-options.json の sdkVersion の値からわかる) ので、 page-mod モジュールのバグが影響して結果的にメモリリークが発生している可能性が高い。 なので 1.0b5 で xpi をビルドすればメモリリークに関しては解決するのではないかと思う。

一応 Add-on SDK 1.0b5 を使って xpi をビルドして、メモリリークが解消されるかを調べてみた。 cfx xpi でビルドする前に cfx run で動かしてみて、 Add-on SDK のduprecated warning が出ていた箇所を機械的に修正し、その後 cfx xpi でビルドした xpi を新しく作ったプロファイルにいれた。このプロファイルを profile-C とする。

  • profile-C: ダウンロードしたアドオン版 AutoPagerize のソースコードを duprecated warning が出ないように修正して Add-on SDK 1.0b5 でビルドし、出来上がった xpi を新しく作成したプロファイルにいれ、その後 profile-A と同様に extensions/jid0-tKjnEA5X3eBoP5HnqjBYQ4U3AcM@jetpack/resources/jid0-tkjnea5x3ebop5hnqjbyq4u3acm-autopagerize-data/autopagerize.user.js の MIN_REQUEST_INTERVAL を 1 に変更したもの

上で実行したのと同様に profile-C の memory in use の値を調べた結果は以下の通り。 比較のため上の profile-A と profile-B の結果も一緒に並べている。

profile-A:

  • 1回目: 68,454,936
  • 2回目: 79,872,508
  • 3回目: 89,678,316
  • 4回目: 99,641,002
  • 5回目: 109,578,684

profile-B:

  • 1回目: 86,942,136
  • 2回目: 53,991,244
  • 3回目: 85,488,772
  • 4回目: 86,714,816
  • 5回目: 85,739,944

profile-C:

  • 1回目: 68,808,860
  • 2回目: 68,900,826
  • 3回目: 69,095,090
  • 4回目: 69,219,782
  • 5回目: 69,226,282

profile-C の memory in use の値が少し増加する傾向にあるのが気になるが、 増加量が一定していないことと、 profile-A と比較して profile-C の memory in use の値の増加は小さくなっていることから、 メモリリークは解消されたとみてよいのではないかと思う。

結論

  • 2011-05-14 現在配布されているアドオン版の AutoPagerize を使用するとメモリリークが発生する
  • AutoPagerize がメモリリークしているのは、 AutoPagerize 自体の問題ではなく Jetpack Add-on SDK 側の問題
  • このメモリリークを引き起こす Add-on SDK のバグは 1.0b5 で既に修正されている
  • なので新しい Add-on SDK で xpi を作成すればメモリリークに関しては問題が解決するだろう
  • 作者が Add-on SDK 1.0b5 or later で アドオン版 AutoPageize をビルドして配布してくれるのを待てばよい

という感じ。