2013-06-03 16 views
31

私はフォームの中にブラウザのメモリが増加し始めていることに気付きました(これはタスクマネージャーからはっきりと分かります)。 IE 9では、いくつかの使用後に500MBを簡単に超えますが、クロムはより復元力があります(同じテストを使用して200MBになります)。Javascriptのメモリリーク:デタッチされたDOMツリー

私はこの問題をデバッグするためにChromeの開発ツールを使用しています。

detached dom tree screenshot

私は、これはメモリリークがあることを確認することができると仮定しています:私は独立したDOMツリーの数が多いことに気づきました。それは正しいでしょうか? 第2に、問題の根本的な原因を特定する方法を見つける必要があります。これらのアイテムが再生されるのを阻止しているものを特定するために、保持ツリーを使用する必要があることはわかっています。しかし、私は保持ツリーの使い方を知ることはできません。たとえば、上記のスクリーンショットの保持ツリーはどういう意味ですか?

ご協力いただければ幸いです。

+2

いくつかのコードを使って '私がフォームにいる間にブラウザのメモリが増え始める 'ことを明確にできますか?それはメモリリークを見つけるのに役立ちます。 – Ikrom

+0

[この他の質問/回答](http://stackoverflow.com/questions/11930050/finding-js-memory-leak-in-chrome-dev-tools)は役に立ちますか? – msung

答えて

25

DOM要素を参照するコードを記述する際には、多くの考慮事項があります。しかし、それは基本的に、いくつかの単純なポイントにまでぼんやりしています -

a。ローカル機能内では常に参照をクリアしてください

var menu = $('body #menu'); 
// do something with menu 
. 
. 
. 
menu = null; 

bです。要素データの一部として参照を保存しないでください。.data()

c。はい、1は、検索要素がページを遅くすることができますことを主張することができますが、パフォーマンスに比べ、巨大なを打つ際に遅延が非常に最小限である識別子

function attachClick(){ 
     var someDiv = $('#someDiv'); 

     someDiv.click(function(){ 
     var a = someDiv....; 
     //Wrong. Instead of doing this.. 
     }); 


     someDiv.click(function(){ 
     var a = $('#someDiv'); 
     //Pass the identifier/selector and then use it to find the element 
     });  


     var myFunc = function(){ 
     var a = someDiv; 
     //using a variable from outside scope here - big DON'T!    
     } 
    } 

を渡す代わりに、閉鎖/インラインハンドラ内のDOM参照を使用しないようにしてくださいヒープがespを引き起こします。大規模な単一ページのアプリケーションではしたがって、#3は賛否両論の重さを測った後でなければなりません。

UPDATE

D(これは私の場合にはかなり助けてやりました)。匿名関数の使用を避ける - イベントハンドラとローカル関数の名前を付けると、ヒープスナップショットをプロファイリングしたり調べたりする際に役立ちます。

+0

私は(c)に同意しないと、後続の関数呼び出しでクロージャが返された場合や、渡されたDOM要素への参照を保持する操作(またはjQueryラップ要素) - すなわち静的リストに要素を格納したり、何らかの種類の循環参照を作成したりすることができます。要素をメソッドに渡すだけで問題が発生する例がありますか? – Pebbl

+2

@pebbl:コードをチェックしました。あなたが正しい。私は閉鎖を意味し、単純にメソッドに渡すのではありません。上記の修正例。 –

+0

ああ、いいですね。明確化のおかげで、はるかに明確になりました。 – Pebbl

2

あなたのコードは多くのDOMサブツリーを作成し、それをjavascriptから参照しているようです。 Detached DOMツリーから要素を選択する必要があります。スナップショットに従って、Textエレメントを選択する必要があります。リテーナーツリーを見てください。

このツリーは、オブジェクトを有効に保つすべてのパスを表示します。少なくとも1つのパス、通常は最短パスがウィンドウオブジェクトに移動します。コードに慣れていれば、削除する必要のあるオブジェクトをそのパスで簡単に見つけることができますが、そうではありません。パスには多くのオブジェクトが存在する可能性があります。距離が最も小さいオブジェクトはもっと面白いです。

関連する問題