web-dev-qa-db-ja.com

JavaScriptのガベージコレクションをトリガーできますか?

JavaScriptのガベージコレクションをトリガーしたい。出来ますか?なぜこれを行いたい、またはしたくないのですか?

44
Abhinav

私はあなたの質問の一つに答えを求めるために小さな旅に出ました:それは可能ですか?

町中の人々は、参照を削除するとうまくいくと言っています。一部の人々は、オブジェクトのワイプは追加の保証であると言います( )。それで、本のあらゆるトリックを試すスクリプトを書きました。そして、Chrome(22.0.1229.79)とIE(9.0.8112.16421)のガベージコレクションでそれを見て驚いた機能しないようです。 Firefox(15.0.1)は、1つを除いて大きな欠点なしで管理しました(以下のケース4fを参照)。

擬似コードでは、テストは次のようになります。

  1. ある種のオブジェクトを保持するコンテナ、配列を作成します。このコンテナをBertilと呼びます。

  2. その中のすべてのオブジェクトは、Bertilの要素として、プロパティとして宣言された独自の配列コンテナを持つ必要があります。この配列は、大量のバイトを保持します。 Bertilの要素のいずれかをオブジェクトJoshuaと呼びます。各ジョシュアのバイト配列はSmithと呼ばれます。

    頼りになるマインドマップを次に示します。

    Bertil [オブジェクトの配列]-> Joshua [オブジェクト]-> Smith [バイトの配列]->名前のない[バイト]。

  3. 使用可能なメモリを使い果たしたら、1、2秒待ち、次の「破壊アルゴリズム」のいずれかを実行します。

    4a。メインオブジェクトコンテナBertilで削除オペランドをスローします。

    4b。そのコンテナ内のすべてのオブジェクトに削除オペランドをスローし、生きているすべてのジョシュアを殺します。

    4c。あらゆるバイト配列であるスミスに削除オペランドをスローします。

    4d。すべてのジョシュアにNULLを割り当てます。

    4e。すべてのジョシュアに未定義を割り当てます。

    4f。ジョシュアが保持しているすべてのバイトを手動で削除します。

    4g。上記のすべてを正常な順序で実行します。

それで何が起こったのですか?4aand4b、ブラウザのガベージコレクター(GC)は起動しませんでした。4cから4eの場合、Firefoxは概念実証を開始しました。メモリはすぐに回収されました。テスト構成として使用されるいくつかの変数の現在のハードコードされたデフォルト値、case4fおよび4eChromeがハングしたため、そこで結論を出すことはできません。独自の変数を使用して独自のテストを自由に行うことができます。リンクは間もなく公開されます。 IEはケース4fと4eを生き延びましたが、彼のGCはいつものように死んでいました。予想外に、Firefoxは生き残りましたが、4fに合格しませんでした。 Firefoxは生き残り、4gをパスしました。

ブラウザーのGCの起動に失敗したすべてのケースで、少なくとも10分間待機しても問題は解決しませんでした。また、ページ全体をリロードすると、メモリフットプリントが2倍になりました。

私の結論は、コードに恐ろしいエラーを犯したに違いない、またはあなたの質問に対する答えは「いいえ、GCをトリガーすることはできません」ということです。そうしようとするたびに、私たちは厳しく罰せられ、砂に頭を刺さなければなりません。これらのテストケースを自分で試してみることをお勧めします。コードを見て、詳細についてコメントしてください。また、ページをダウンロードしてスクリプトを書き換え、GCをより適切な方法でトリガーできるかどうかを確認します。 ChromeとIEには有効なガベージコレクターがないとは信じられません。

http://martinandersson.com/dev/gc_test/?case=1

http://martinandersson.com/dev/gc_test/?case=2

http://martinandersson.com/dev/gc_test/?case=

http://martinandersson.com/dev/gc_test/?case=4

http://martinandersson.com/dev/gc_test/?case=5

http://martinandersson.com/dev/gc_test/?case=6

http://martinandersson.com/dev/gc_test/?case=7

43

IEとOperaでJavaScriptガベージコレクターを手動でトリガーすることができますが、推奨されないため、まったく使用しないことをお勧めします。

インターネットエクスプローラ:

window.CollectGarbage()

Opera 7以降:

window.opera.collect()
7
masterspambot

ガベージコレクションは自動的に実行されます。いつどのように実行され、参照されていないオブジェクトを実際に解放するかは、完全に実装固有です。

何かを解放したい場合は、javascriptから参照をクリアするだけです。ガベージコレクターはそれを解放します。

私の知る限り、ガベージコレクションを手動でトリガーする方法はありません。

これを行う必要があると思う理由を説明したり、これを実行したり、関連するコードを表示したい場合は、代替手段が何であるかを説明できる場合があります。

6
jfriend00
  1. グローバル変数のコードを確認してください。 ajax呼び出しを介してデータが保存され、どこかで参照されたため、これを考慮しなかった可能性があります。
  2. 解決策として、巨大なデータ処理を匿名関数呼び出しにラップし、この呼び出し内でローカル変数のみを使用して、グローバルスコープ内のデータの参照を防止する必要があります。
  3. または、使用されているすべてのグローバル変数をnullに割り当てることができます。
  4. この質問 も確認してください。答えの3番目の例を見てください。あなたの巨大なデータオブジェクトはまだ非同期呼び出しクロージャによって参照されているかもしれません。
3
mixel

この回答 は、Geckoベースのブラウザー用の次のガベージコレクションリクエストコードを提案します。

    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
      .getInterface(Components.interfaces.nsIDOMWindowUtils)
      .garbageCollect();        
2
Daniel Wahlberg

私はトレバープライムの答えを読んでいて、それは私にくすくす笑いを与えましたが、それから彼は何かをしていることに気付きました。

  1. ページをリロードすると、「ガベージコレクション」が実行されます。
  2. location.reload()またはページを更新する代替手段。
  3. 必要なデータを永続化するためのJSON.parse/stringifyおよびlocalStorage.getItem/setItem。
  4. ユーザーエクスペリエンスのためにページをリロードするiframe。

必要なことは、iframeでコードを実行し、iframeページを更新しながら、localStorageに有用な情報を保存することだけです。 DOMにアクセスするには、iframeがメインページと同じドメインにあることを確認する必要があります。

Iframeなしでも実行できますが、ページが視覚的にリセットされるため、ユーザーエクスペリエンスが低下することは間違いありません。

1
maelwyn

この質問に出くわして、最近の調査結果と共有することにしました。 WeakMapの適切な処理をChromeで確認しましたが、実際には問題ありません。

1)var wm = new WeakMap()

2)var d = document.createElement('div')

3)wm.set(d, {})

この段階で、弱いマップはdがまだ要素を参照しているエントリの原因を保持します

4)d = null

この段階では、要素を参照するものはなく、弱く参照されるオブジェクトです。実際、数分後にエントリが消え、ガベージコレクションが行われます。

同じことをしたが、要素をDOMに追加した場合、それは回収されず、正しく、DOMから削除され、まだ収集されるのを待っていた:)

1
GullerYA

はい、ページを再ロードすることでガベージコレクションをトリガーできます。

ファクトリパターンを使用してオブジェクトを再利用することを検討すると、作成されるオブジェクトの数を大幅に削減できます。特に、同じオブジェクトを継続的に作成している場合。

Factory Patternsを読む必要がある場合は、Ross HarmesとDustin Diazによる本書「Pro Javascript Design Patterns」を入手し、APressから出版してください。

1
Trevor Prime

他の回答に示されているように、GCをトリガーする方法がないことが真実である場合、適切なブラウザー標準グループがこれを行うためにウィンドウまたはドキュメントに新しいJavaScript関数を追加します。アニメーションやその他の優先度の高い操作(サウンド出力?)がGCによって中断されないように、Webページが独自に選択したときにGCをトリガーできるようにすると便利です。

これは、「私たちは常にこの方法で行ってきました。ボートを揺らさないでください」症候群の別のケースかもしれません。

追加:

MDNは、「Components.utils.schedulePreciseGC」という関数を文書化します。これにより、GCが完了したときに呼び出されるコールバック関数を使用して、ページが将来GCをスケジュールできるようになります。これは、Firefox以外のブラウザには存在しない場合があります。ドキュメントは不明です。この関数は、アニメーションの前に使用できる場合があります。テストする必要があります。

0
David Spector