silverlight記憶體問題總結(二)—javascript記憶體泄露

來源:互聯網
上載者:User

   對於javasript這門語言,我的感觸還是比較多的,從畢業到現在這門語言我一直在使用。在ASP年代末期,這門語言開始被很多開發人員所鄙視,很多人都覺得JavaScript只會彈出alert,只會實現一些簡單的功能,最讓人厭惡的是出現語法錯誤時候,會連續不斷地彈出錯誤,直到開發人員絕望為止,直到前端使用者窒息為止。隨著Ajax 的出現,Google Map的成功,以及各種JS架構出現,JavaScript開始再一次被開發人員重視它,CSDN 曾經一度用“王者歸來”這四個字來形容它。相比.net而言,我的javscript經驗應該是比較多的,從畢業到現在,一直在用從未間斷過,幾個流行架構 Ext,jQuery,prototype 都有使用過,對JS的物件導向的理解還是比較到位,對JAVASCRIT 在IE系列瀏覽器和Firefox之間的差異也略知一二,當然隨著IE9的出現,這種差異會越來越少。曾經有一個想法,把gof 的23個設計模式用JavaScript實現,不過後來發現在部落格園上已經有人這麼做了,我的興緻一下子蕩然無存。

    兩塊silverlight之間的資料通訊,需要拿javascript做橋樑,因為好幾個線程都是在死迴圈的跑,有些資料互動是要用到javascript,導致很多javascript代碼一直在死迴圈調用,由此而引出記憶體泄露。

    javascript的記憶體釋放也是自動回收的,基本原理也是當一個對象沒人任何指標指向它時記憶體回收行程就可以啟動回收了。造成javascript 泄露的主要原因:循環參考,閉包。循環參考道理其實很好懂 如A=》B  B=》C  C=》A,導致 A,B,C三個對象都無法釋放,不要小看該列子,當代碼多起來龐大起來,這三者的關係是很難被發現。 至於閉包,範圍鏈原理,網上有很多介紹的文章,無奈由於專業的緣故,本人沒學過編譯原理,所以看這些文章有些吃力,有興趣可以查閱(http://kevinpeng.javaeye.com/blog/682653)。閉包泄露很多時候都是由於javascript對象和Dom互相引用,以及一些事件訂閱後又沒有拆除這些訂閱造成.

DOM引用造成的記憶體泄露:

 

 

      function  LeakMemory()  // This function can cause  Cross-Page Leaks 
{
var hostElement = document.getElementById( " hostElement " );
// Do it a lot, look at Task Manager for memory response
for (i = 0 ; i < 5000 ; i ++ )
{
var parentDiv = document.createElement( " <div onClick='foo()'> " );
var childDiv = document.createElement( " <div onClick='foo()'> " );
// This will leak a temporary object
parentDiv.appendChild(childDiv);
hostElement.appendChild(parentDiv);
hostElement.removeChild(parentDiv);
parentDiv.removeChild(childDiv);
parentDiv = null ;
childDiv = null ;
}
hostElement = null ;
}
function CleanMemory() // This Function can not cause Cross-Page Leaks
{
var hostElement = document.getElementById( " hostElement " );
// Do it a lot, look at Task Manager for memory response
for (i = 0 ; i < 5000 ; i ++ )
{
var parentDiv = document.createElement( " <div onClick='foo()'> " );
var childDiv = document.createElement( " <div onClick='foo()'> " );
// Changing the order is important, this won't leak
hostElement.appendChild(parentDiv);
parentDiv.appendChild(childDiv);
hostElement.removeChild(parentDiv);
parentDiv.removeChild(childDiv);
parentDiv = null ;
childDiv = null ;
}
hostElement = null ;
}
</ script >
</ head >
< body >
< button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
< button onclick = " CleanMemory() " > Clean Insert </ button >
< div id = " hostElement " ></ div >
</ body >
</ html >

事件的訂閱後沒退訂後造成的記憶體泄露:

function leakmaybe() {
var elm = document.createElement( " DIV " );
elm.onclick = function () {
return 2 + 2 ;
}
}
for ( var i = 0 ; i 10000 ; i ++ ) {
leakmaybe();
} //上述迴圈中不斷調用leakmaybe,每調用一次就會訂閱一個onclick事件,如果是死迴圈的話,就會出現泄露。


javascript的在IE系列的記憶體泄露很多都是IE瀏覽器本身的BUG,但是微軟死活不認帳,Eric Lippert是IE引擎開發組的成員,下面是他的原話:Don't use closures unless you really need closure semantics. In most cases, non-nested functions are the right way to go.他把這個BUG推給開發人員,認為是開發人員使用不當造成。Silverlight 記憶體釋放不了,微軟也不怎麼認賬,後面文章會提到。

    關於javascript 記憶體泄露,我也查閱了很多文章,但是我和我實際項目中都不怎麼搭調,唯一個搭調的是setTimeout和setInterval,我在網上查了一下 很多人說這兩個方法在計數器方面會造成記憶體泄露,但是我自己本機上做了測試不會泄露,好像IE6好像會,但是IE8絕對不會,我自己本機是IE8的。其實setTimeout和setInterval只是創造了一種死迴圈的環境,實際記憶體泄露應該不關他們的事情。最後發現記憶體泄露是由於這句話 :     

 eval("var list=" + a),這行代碼主要是把一個字串解析成javascript對象,據國外的老鳥解釋,在解析的時候會產生一個臨時對象,這個臨時對象沒辦法釋放,導致泄露,一個晚上泄露大概在14M左右。還有一個泄露地方是心跳驗證(驗證使用許可權的),每跳一次都要發起AJAX請求,我估計是AJAX對象每次都重建,但是又沒辦法釋放導致的,這個地方造成的泄露是一個晚上36M。最後給一個技巧,如果頁面是javascript泄露造成的,只要最小化一下記憶體就會釋放的掉,這是衡量JS泄露的個人的一個小技巧,當然還有待有大量事實的驗證

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.