アドオン版 AutoPagerize のメモリリークに関する調査
Firefox4 用アドオンの AutoPagerize がメモリリークしているという話があった。
- http://twitter.com/#!/zapa/statuses/52351101382557697
- http://www.goinkyo.jp/isaoa/?i=2011/04/02-221540
- http://lufesu.blog3.fc2.com/blog-entry-54.html
- http://d.hatena.ne.jp/ima314/20110413/1302712902
- http://twitter.com/#!/Dita_69/status/59039558909706240
- http://twitter.com/#!/nagas/statuses/65150690221236224
アドオン版の 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)を用いた。
検証方法
準備:
- https://bitbucket.org/xKairouan/apmemleaktest のスクリプトと適当な画像 (http://blog-imgs-44-origin.fc2.com/d/a/n/danboruparty/20110424005.jpg など)を同じディレクトリに入れる
- https://bitbucket.org/xKairouan/apmemleaktest のスクリプトを python apmemleaktest.py 100 として実行
検証:
- Firefox を プロファイルを指定して起動
- about:memory を開く
- 別のタブで http://localhost:8080/ を開く
- AutoPagerize が 100 ページまで読み込んで停止するまでスクロールする
- 30秒待つ
- about:memory を更新して memory in use を記録
- http://localhost:8080/ を開いていたタブを閉じる
- 3 に戻る
- 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 をビルドして配布してくれるのを待てばよい
という感じ。