Ajax有可能導致內存泄漏?(網(wǎng)易博客內存泄漏剖析)
2006年11月19日 09:45 作者:
STORM昨晚,為了驗證網(wǎng)易博客中計算點(diǎn)擊量的Flash如何工作,一直刷新blog,大約進(jìn)行了二三十次。早晨,關(guān)機前,覺(jué)得機器有些慢,赫然發(fā)現IE占用了接近200M內存,關(guān)閉其它窗口,只剩網(wǎng)易博客,資源占用依然超過(guò)了170M。
忽然想到了Javascript,想到了Ajax,是否因為Javascript中某些對象無(wú)法被回收造成的?一夜沒(méi)睡,實(shí)在沒(méi)精力再去分析網(wǎng)易的Javascript,百度一下,發(fā)現了以下內容。先貼這里,醒來(lái)再驗證。
創(chuàng )建XMLHttpRequest對象的方式有兩種:一是作為全局變量,二是作為局部變量,那么這兩種方式下的AJAX對象的生命周期如何?考慮這個(gè)問(wèn)題的原因是,如果頁(yè)面不停的使用不同XMLHttpRequest對象請求,并且AJAX對象的生命周期是全局的,那么顯然內存最終會(huì )被耗盡!
解決這個(gè)問(wèn)題的方法似乎只能以局部變量方式創(chuàng )建XMLHttpRequest對象,但是局部創(chuàng )建的AJAX對象占用的內存什么時(shí)候被回收?請看下面的代碼,是否creatConnect中send調用后就被回收?如果是這樣那就糟糕了,因為當服務(wù)器有結果返回時(shí)再也找到不到ajax對象的readyState、responseText等屬性,因此結論是瀏覽器不知道什么時(shí)候該回收ajax對象占用的內存,因為它永遠不知道回調函數會(huì )什么時(shí)候被調用!按照這個(gè)結論,如果在一個(gè)頁(yè)面不停的創(chuàng )建局部的AJAX對象,它是會(huì )吃光內存的!
繼續使用下面的例子進(jìn)行測試,但是為了讓測試結果更明顯些將obj[i].i=“f“;中“f“變?yōu)榇蠖蔚奈谋荆╫bj本來(lái)也是局部變量,當函數調用完就會(huì )被銷(xiāo)毀,但是它在這個(gè)函數中也許不一樣)。
我的測試結果(點(diǎn)擊test1)是它似乎真的會(huì )吃光內存!大概不到一個(gè)小時(shí)的時(shí)間IE線(xiàn)程占用內存達到了300多M,后來(lái)系統變慢以至很難響應。(由于PC會(huì )使用虛擬內存,所以將虛擬內存調到3-400M,同時(shí)將系統的空間搞到只剩下1、200M以下,這樣效果會(huì )更快些,否則系統會(huì )使用頁(yè)面文件)
不知道我的測試方法和測試結果是否正確,如果是的話(huà),哪位高人有比較好的方法來(lái)解決這樣的內存問(wèn)題?因為在某些情況下web應用可能真的需要不停的創(chuàng )建AJAX對象,謝謝!
function creatConnect(url)
{
var ajax=null;
if(window.ActiveXObject)
{
ajax=new ActiveXObject(“Microsoft.XMLHTTP“);
}
else if(window.XMLHttpRequest)
{
ajax=new XMLHttpRequest();
}
ajax.open(“GET“,url,true);
var obj=new Array();
for(var i=0;i<100;i++)
{
obj[i]=new Object();
obj[i].i=“f“;
}
ajax.onreadystatechange=function (){
if(ajax.readyState==4)
{
document.getElementById(“show“).innerHTML=(new Date()).getTime();
}
};
ajax.send(null);
}
var timer=null;
function test1()
{
clearTimeout(timer);
timer=null;
creatConnect(“test.htm“);
timer=setTimeout(“test1()“,1);
}
function test2()
{
clearTimeout(timer);
timer=null;
var obj=new Array();
for(var i=0;i<100;i++)
{
obj[i]=new Object();
obj[i].i=“f“;
}
document.getElementById(“show“).innerHTML=(new Date()).getTime();
timer=setTimeout(“test2()“,1);
}
function stop()
{
clearTimeout(timer);
timer=null;
}