LDR のメモリ・リーク問題について

フィード一覧の全フォルダを一気に開くスクリプトを書こうと思い、ソースを読んでいたら、ある問題にぶつかりました。

ツリー表示における各ルート (フォルダ) は TreeView というオブジェクトによって表されています。そして、それらは後からの参照のためにテーブルに格納されています。

問題と言うのは、作成された全ての TreeView インスタンスが格納されっぱなしになってしまう、ということなんです。

リロードを行う度に新たに TreeView インスタンスが作成されるんですが、その際、もう使われることのない古いインスタンス (への参照) は捨てられずに残ってしまうんですね。

例えばレート表示の場合、リロード回数掛ける 6 個のインスタンスが保持されることになり、これがメモリ・リークとなってしまいます。

以下をアドレスバーで実行して確認してみてください:

javascript:alert(keys(TreeView.instance))

リロードする度に増えていくのがお分かりだと思います。


そこで、リロード前にインスタンスの ID (以下のように単純なカウンタ変数によって決定されます) をリセットするのはどうかと考えました:

register_hook("BEFORE_SUBS_LOAD", function() {
  TreeView.count = 0;
});

ところが、これは上手くいきません。BEFORE_SUBS_LOAD という名前のフックが、綴りのミスで作成されていないためです (近ごろ一覧のリロード時に左上の青いアイコンが回転しないのも同じ理由によります)。

なので、代わりにリロード後 (AFTER_SUBS_LOAD) のフックを使えばとりあえずは問題解決です。


P.S.
報告のため、関係の無い最新記事に TB させて頂きます。


追記 [20061118]:

あ、フックを使う方法ではちょっと不十分だったかもしれません。新着フィードが 100 以上あった場合に表示が複数回行われるわけなんですが、その際にも古いインスタンスが残ってしまうんですね。

あと、フィード一覧絞込みスクリプトでも同様の問題が生じているはずですので、なるべく早く修正したいと思います。


ともあれ、フォルダの開閉スクリプトを書いてみました:

javascript:(function(m){each(TreeView.instance,function(v){v[m]()})})("toggle")

最後の toggle の部分を open や close にすることでそれぞれ開閉専用のブックマークレットを作ることが出来ます。

ついでに、クロージャ版:

function tv(method) {
  method = method || "toggle";
  return function() {
    each(TreeView.instance, function(v){v[method]()});
    message("TreeView: "+method);
  };
}
register_command("+", tv("open"));
register_command("-", tv("close"));


追記 [20061120]:

フックに代わる方法として、以下のようにしてみました。

var SV = Subscribe.View;
SV.prototype.clear = SV.prototype.clear.addAfter(
  function(){ TreeView.count=0 }
);

これだと絞込みスクリプトの方は弄る必要がありません。

(ここに追記するだけでは拾ってもらえないかも知れませんが、どうもメールフォームだと反応が得られないので…)


mala さんへ、返信:

パッチ等の件について、私のしたことで気分を害されているのかな、という感覚は薄々感じていました。顧客サービスなんだから、ということで思い上がっていた部分があったと思います。反省します。

また、反応を頂けないことで、「読んで頂いてないのかな」という不安を勝手に深めておりました。この点に関しては安心しました。

今後は冷静で客観的な記述を心がけたいと思います。本当に失礼いたしました。