ajaxで定期的に鯖から何かget、とかさせていると、そのたびに4K〜16Kほどのメモリを食って、離さにゃい気がする@IEの件で、とりあえず何とかにゃったのでメモ。
まずリークする場合の、激しく簡略化したソース。
function post2(arg){
var req = new ActiveXObject("Msxml2.XMLHTTP");
req.onreadystatechange = function(){
if(req == undefined) { return 9; }
if(req.readyState != 4) { return 4; }
if(req.status != 200) { return 2; }
window.status = "ok";
setTimeout('post2()',1000);
}
req.open("POST", "./?mode=test", true);
req.send("test"+arg);
}
よくそこらへんで紹介されてる方法にゃんだが、reqが開放されずに残るのよね。にゃのでしばらく放置しておくとIEの使用メモリが50Mとかににゃってたりする。
ので、使用後(ここではsetTimeoutの後とか)にreq = null;しにゃければにゃらにゃい。
こんにゃメモリ管理はお任せのつもりだったので、身近にゃ低機能言語としてマーク。うーん、そりゃまぁ使わにゃくにゃったかどうかの判定て難しそうだけど、ダメにゃ場合はダメとリファレンスに大きく載せておくべきだと思うにゃぁ。読んだこと無いけど。ページ丸ごと書き換え〜とかしてると数k単位どころか1M単位で使用メモリが増加するんでは無かろうか。
あと、こういう単純にゃ構造にゃらreq = nullを1つ入れれば解決にゃんだが、もっと構造がぐちょってたり、DOM関連で入れ子してたりするとたぶんこの程度では無理と思われる。再帰で
for(var x = obj.length;x--;){
obj[x] = null;
delete obj[x];
}
して末端までnullで埋めたり、グローバル変数を
var n=乱数;
eval("TMP_"+n+"=obj");
で確保しておいて、nを参照せずにそのまま受け渡すとか(笑)
いろいろダメっぽい解決法を考えてみたが非常にアレにゃので、おしえておねがいさみあドン。
さらにメモだが、上と関係にゃいところで基本的ハマり要素として、
X=[];
n=5;
X[n]=0;
X[n]=null;
delete X[n];
とかしても、X[n]が確保したメモリは解放されにゃい。検証してにゃいけど、一度確保した連想配列は開放されにゃいというか何というか。よって、perlのハッシュのように用いるとえらいことににゃる(笑)
上の変数reqをグローバルにゃ配列に作っちゃえば安易に消せるだろうと思って組んだら、配列Xそのものを消さにゃいとメモリ解放されにゃかったりしてハマったわけで。
しかも、この手の配列を参照するときに線形検索してるようにゃ気がする。よくわからんが変に遅い。もうめんどくさいからperlのハッシュ機構載せてくれと。
それにしてもこの問題、根が深いにゃぁ。IEが単にダメってことだと思うけど、例えばgoogle newsを1週間くらい開いていたIEって数百Mもメモリ食ってるわけで、根本的にゃところでやばいことが起きてそうにゃ気がする。