33

グーグルクローム(バージョン20.0.1132.47、Ubuntu 11.04 64ビット)のガベージコレクションについて質問があります。

ヒープダンプを比較し、メモリリークをチェックしているときに、クリーンアップされないインスタンスをいくつか発見しました。通常、この動作はプログラマーエラーまで追跡できますが、この場合、私はかなり無知です。

次のスクリーンショットを見てください 'bound_this'によってのみ参照されるインスタンス(子)を示すヒープダンプのスクリーンショット

インスタンス「child@610739」は、子インスタンス自体の関数に属する「bound_this」インスタンスによってのみ参照されます。したがって、私の理解では、子インスタンスはガベージコレクションされる必要があります。これは、子インスタンスを保持している他の唯一の参照が子インスタンス自体であるためです('bound_this'関数を介して)。

chromeの'native_bind'関数にマップするunderscore.js''bindAll 'ユーティリティ関数(underscore.js#bindAll)を使用しています(bound_thisのECMAスクリプトwiki

私はここで明らかな何かを見逃していますか?もしそうなら、誰かがこれらのインスタンスを生き続けているものを説明できますか?

更新:
その間に、これらのぶら下がっているインスタンスを表示しないchrominium(18.0.1025.168(Developer Build 134367 Linux)Ubuntu 11.10)で同じアプリケーションをテストしました。

更新2:
jsfiddleスニペットを提供するためのEsailijasのヒントに従って、基本的に行っていることを模倣したもの( http://jsfiddle.net/8gSTR/1/ )を作成しました。残念ながら、このフィドルを実行しても、アプリケーションで発生している不正行為は表示されません。'a'-インスタンスがまだ参照されている間に取得されたヒープダンプは、インスタンスを存続させるwindow.o配列からの参照にもかかわらず、似たようなものに見えます。 上記のjsfiddleの実行中に取得されたヒープダンプ

私の場合(スクリーンショット1)、そのような参照が欠落しているため、chromeがこれらのインスタンスを解放するのを妨げるものがわかりません...

更新3:
隠されたプロパティを有効にするためにloislosのアドバイスに従いました。結果(ブランチの1つが展開されている)は次のスクリーンショットで見ることができますが、それ以上はかかりません。 非表示のプロパティが有効になっているヒープダンプ

4

3 に答える 3

4

これは実際のメモリリークではないが、クロムの奇妙さは正しいというあなたの疑惑は正しいです。

私は最近同じ問題に遭遇しました。IE11はthis.func=_.bind(this.func、this)をメモリリークとして表示しませんが、chromeはガベージ収集ボタンを100回押した後でも表示します。

jsflagナンセンスでchromeを実行し、基になるガベージコレクターを公開して、gcを100回呼び出した後でも、それが表示されます。

それが実際にクロムの漏れではないことを証明する簡単な方法は、ブラウザで小さな問題を大きな問題にし、エンジンにアクションを強制することです。

バインドされた関数が割り当てられているインスタンスで、次のような新しいプロパティを割り当てます。

target.WhyAmILeaking = new Array(200000000).join( "YOURNOT");

chromeを使用して3つのスナップショット手法を実行すると、ヒープに存在する文字列が約214mbでクロックインしていることがわかります。建設的なアクション(2番目のスナップショット)をもう一度実行すると、ヒープが423mbになるか、214mbのままになります。それが残っている場合は、元の214mbが収集されたことを証明したとおりに完了します。それが留まらない場合は、破壊的なアクション(3番目のスナップショット)を実行すると、214 MBに戻り、元のアクションが収集されたことも証明されます。

それが423mbのままである場合、サーまたはマダムにリークがあります。

ああ、まったく同じ状況に遭遇した貧しい魂の別のグループ:https ://github.com/jashkenas/backbone/issues/2269#issuecomment-13610969

TL; DR; リークの検出にはIE11を使用してください。

于 2014-03-05T13:04:46.143 に答える
1

私はこれをEcmaScriptで参照しました。この用語は、クラスで「これをバインド」します。

クラスメソッドには「バインドされたこれ」があり、メソッド本体のthisは、このパラメーターが実際にメソッドに渡されるかどうかに関係なく、メソッドが抽出されたクラスインスタンスに常にバインドされます(メソッドへのこのパラメーターは無視されます) 。

ここで、あなたの例ではサンプルスクリプトが与えられていないので、質問に固有にすることはできません。

これがリークではないかどうかを言わなければなりません。

次に、どのオブジェクトでも、スクリプトがバインドされているクラスは、この関数が同じオブジェクトにバインドされているため、クラス/オブジェクトが存在するまでガベージを呼び出しません。親(オブジェクト/クラス)の後にのみガベージコレクションされます。制限付き)スコープが終了します。

これで、タスクが終了するときに循環参照が終了する場合、>>これは再帰の概念のように機能します(概念と同じではありません)。したがって、終了は最後の呼び出しから始まります。逆に..最も内側の呼び出し(最新の呼び出し)が最初に解放されます..など

コードは、関数をバインドして定義し、毎回再利用してはならないため、バグがある必要があります。ただし、バインドしている場合は、正常に機能し、フットプリントがブラウザのメモリプールの制限を超えるまでリークしないはずです。

これが説明されることを願っています。

于 2013-07-16T05:17:14.197 に答える
1

開発者ツールを使用して「強制GC」をトリガーしていますか?それが事実であり、オブジェクトが存続する場合、上記の調査は価値があります。

開発者ツールを介してGCをトリガーしない場合は、GCエンジンの動作が非常に複雑であり、世代別収集(2世代を使用)の概念があることを忘れないでください。

http://www.html5rocks.com/en/tutorials/memory/effectivemanagement/#toc-v8-gc

単純に、若い世代のGCをトリガーするために必要なしきい値に達していないか、オブジェクトが古い世代に保持されているが、古い世代のGCがトリガーされていない可能性があります。

残念ながら、開発者ツールはどの世代がGCされたかを示していないようです。

于 2013-08-08T16:04:51.543 に答える