新しい Progression 開発に向けて、少しづつ技術検証をしているのですが、ちょっとどうしようもない状況に遭遇したのでメモ。
まずは以下の wonderfl を実行してみてください。
※同時に実行すると正しい結果にならないので、ブラウザを再起動するなどして個別に実行してください。
正常な動作
http://wonderfl.kayac.com/code/951c262d616b807aa22f7373c78178e2daa35906
問題版(メモリが完全に解放されない)
http://wonderfl.kayac.com/code/b954ee245607250e4e047ea8cf53a5fbb13e0f49#code_forked
今回は 100000 個の MyObject インスタンスでの検証ですが、だいたい 2.4 MB 程の差が生じてしまっています。
この問題の影響範囲まではまだ確認できていませんが、割とシンプルな操作で解放不能になってしまうので、何かしらの参照が残ってしまっている場合には、解放できないオブジェクトが増えていってしまいそうですね・・・。
この件について何か情報をお持ちの方がいれば、本エントリーのコメント、またはフォーラムまでお寄せください。
追記
クラスメソッドじゃなくてインスタンスメソッドでした。
既知かと思いますが、Dictionaryで、弱参照を利用してメソッドを保持するのは、どうでしょうか?
若干メモリを食いますが、、、
> arkw さん
情報ありがとうございます。
Dictionary に保持する場合、それ自体のメモリ消費は仕方ないとしても、参照を取得する毎に for … in しないと行けない部分がオーバーヘッドとして気になりますね・・・。
function getItem(): {
for ( var item:* in dic ) { return item; }
return null;
}
function hoge(): {
}
var dic:Dictionary = new Dictionary( true );
dic[hoge] = true;
trace( getItem() );
この辺りについてももうちょっと検証して報告しますね。
そもそもの趣旨と全然離れるかもしれませんが、
こういうのはどうですかね?
class MyObject {
public function MyObject() {
// クラスメソッドをローカル変数に代入して破棄する
MyObject.prototype.myMethod = function():void {};
var value:Function = MyObject.prototype.myMethod;
value = null;
}
// public function myMethod():void {
// }
}
> dseg さん
情報ありがとうございます。
匿名関数の場合には、問題なくメモリ解放できそうですね。
ただ、今回の場合にはインスタンスに定義済みのメソッドの参照を格納したいと思っているので、ちょっと趣旨とは違ってしまいますね。