33

フォームを使用しているときにブラウザーのメモリが増加し始めることに気付きました (これはタスク マネージャーで確認できます)。IE 9 では、ある程度使用すると 500MB を簡単に超えますが、chrome はより回復力があります (同じテストを使用すると 200MB になります)。

この問題をデバッグするために、Chrome 開発者ツールを使用しています。多数の Detached DOM ツリーがあることに気付きました。

切り離された dom ツリーのスクリーンショット

これでメモリリークがあることが確認できると思います。それは正しいでしょうか?次に、問題の根本原因を特定する方法を見つける必要があります。保持ツリーを使用して、これらのアイテムの再利用を妨げているものを特定する必要があることはわかっています。しかし、保持木の使い方がわかりません。たとえば、上のスクリーンショットの保持ツリーの意味を教えてください。

どんな援助でも大歓迎です。

4

2 に答える 2

27

DOM 要素を参照するコードを記述する際には、留意すべき考慮事項が数多くあります。しかし、それは基本的にいくつかの単純なポイントに要約されます -

a. ローカル関数内では、常に参照をクリアします

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

b. 要素データの一部として参照を保存しない.data()

c. クロージャー/インライン ハンドラー内で DOM 参照を使用しないようにしてください。代わりに識別子を渡します。

    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!             
      }
    }

はい、要素を検索するとページが遅くなる可能性があると主張できますが、パフォーマンスヒットと比較すると、遅延は非常に最小限です。大きな単一ページのアプリケーションで。したがって、#3 は、長所と短所を比較検討した後にのみ使用する必要があります。(私の場合はかなり役に立ちました)

アップデート

d. 匿名関数を避ける - イベント ハンドラーとローカル関数に名前を付けると、ヒープ スナップショットのプロファイリングや参照を行う際に非常に役立ちます。

于 2013-06-05T09:57:10.237 に答える
2

あなたのコードは多くの DOM サブツリーを作成し、javascript からの参照を保持しているようです。Detached dom ツリーから要素を選択する必要があります。スナップショットによると、テキスト要素を選択する必要があります。そして、リテイナーツリーを調べます。

このツリーには、オブジェクトを存続させるすべてのパスが表示されます。少なくとも 1 つのパス (通常は最短パス) がウィンドウ オブジェクトにつながります。コードに精通している場合は、そのパスで削除する必要があるオブジェクトを簡単に見つけることができますが、そうではありません。パスには、そのようなオブジェクトが多数存在する可能性があります。距離が最小のオブジェクトは、より興味深いものになります。

于 2013-06-04T20:02:36.273 に答える