18

高レベルのオブジェクト指向言語のように JavaScript をより頻繁に使用するようになると、オブジェクトを使い終わったときの C/C++ プログラマーのように考えるようになります。最終的に GC が実行され、混乱が解消されることはわかっていますが、実際にそれを支援するためにできることはありますか?

たとえば、大規模/複雑なプライマリ オブジェクトの配列があります...各プライマリ オブジェクトには、内部に配列やその他の補助オブジェクト参照が含まれる場合があります。プライマリ オブジェクトの処理が完了し、それを配列から削除した場合、GC は最終的に、そのオブジェクトが指している他のすべてのもの、循環内部参照などをすべて把握するでしょう。しかし、ストレージ配列からプライマリオブジェクトを削除してそれを通過し、 array.length=0 のすべての配列と reference=null のすべてのオブジェクトを基本的に GC ジョブを簡単にするために削除することは理にかなっています (たとえば、参照を明示的に削除すると、GC が追跡)?必要に応じて、手動デストラクタのようなものです。それを行う価値はありますか、それともほとんどまたはまったく得られないために時間/労力を無駄にしていますか?

これはGCの質問(Javaなども)の一般的な理論であると思いますが、この質問の目的のために主にJavaScriptに興味があります。

ありがとう!

4

3 に答える 3

5

めったに。

これは、決してないこととは異なります。

一般に、合理的な方法で開発すれば、未使用のオブジェクトは適切に範囲外になり、ガベージ コレクターは単に期待どおりに機能します。そして、自分が何をしているのかを本当に理解していない限り、ガベージ コレクターがその仕事をするのを助けるための努力は、多くの場合、意図したとおりには機能しません。ガベージ コレクションは、さまざまな Javascript エンジンの作成者によって大幅な最適化が行われた領域です。一般に、次の場合を除き、それを台無しにするべきではありません。

  • 分析ツールから得た確かな数字で、本当に必要なものがあることを証明しました。
  • ガベージ コレクターを支援するために、実際に何を変更する必要があるかを実際に理解していることを示すことができます。

これらのいずれも、達成するのは容易ではありません。

したがって、おそらく最良の答えは、例外を理解するのに十分なほど進んでいない限り、おそらくこれについて心配するべきではないということです.

于 2012-12-20T19:36:07.147 に答える
5

これは特定のガベージ コレクターに依存する可能性があるため、答えは使用している JavaScript エンジンによって異なります。

最初に、最良のアプリケーション コードは 2 つのことを行うことに注意してください。機能とパフォーマンスの技術的目標を達成し、変化に対する回復力があります。追加のコードは、追加された複雑さを正当化するのに十分な目的を果たす必要があります。

そうは言っても、Chrome で使用される JavaScript エンジンであるV8 に関する Google のメモによると、

V8 は、ガベージ コレクションと呼ばれるプロセスで不要になったオブジェクトによって使用されたメモリを再利用します。高速なオブジェクトの割り当て、短いガベージ コレクションの一時停止、およびメモリの断片化がないことを保証するために、V8 は、世代別の正確なガベージ コレクタを採用しています。これは、V8 が次のことを意味します。

  • ガベージ コレクション サイクルの実行時にプログラムの実行を停止します。
  • ほとんどのガベージ コレクション サイクルで、オブジェクト ヒープの一部のみを処理します。これにより、アプリケーションの停止による影響が最小限に抑えられます。
  • すべてのオブジェクトとポインタがメモリ内のどこにあるかを常に正確に認識しています。これにより、メモリ リークの原因となる可能性がある、オブジェクトをポインターとして誤って識別することが回避されます。

V8 では、オブジェクト ヒープは 2 つの部分に分割されます。オブジェクトが作成される新しいスペースと、ガベージ コレクション サイクルを生き残ったオブジェクトがプロモートされる古いスペースです。オブジェクトがガベージ コレクション サイクルで移動されると、V8 はそのオブジェクトへのすべてのポインターを更新します。

世代別ガベージ コレクターは、ヒープ間でオブジェクトを移動する傾向があり、すべてのライブ オブジェクトが宛先ヒープに移動されます。宛先に移動されていないものはすべてガベージと見なされます。V8 ガベージ コレクターがライブ オブジェクトをどのように識別するかは明確ではありませんが、手がかりとして他の GC 実装を調べることができます。

十分に文書化された GC 実装の動作の例として、Java の Concurrent Mark-Sweep コレクター:

  1. アプリケーションを停止します。
  2. アプリケーション コードから到達可能なオブジェクトのリストを作成します。
  3. アプリケーションを再開します。並行して、CMS コレクターは「マーク」フェーズを実行します。このフェーズでは、推移的に到達可能なオブジェクトを「ガベージではない」としてマークします。これはプログラムの実行と並行しているため、アプリケーションによって行われた参照の変更も追跡します。
  4. アプリケーションを停止します。
  5. 2 番目の (「リマーク」) フェーズを実行して、新しく到達可能なオブジェクトをマークします。
  6. アプリケーションを再開します。並行して、ガベージとして識別されたすべてのオブジェクトを「一掃」し、ヒープ ブロックを再利用します。

これは基本的に、特定のノードのセットから始まるグラフ トラバーサルです。切断されたオブジェクトにはアクセスできないため、他の切断されたオブジェクトへの接続性は機能しません。

http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdfには、Java ガベージ コレクションの仕組みに関するホワイト ペーパーがあります。ガベージ コレクションは Java に固有のものではないため、Java 仮想マシンと JavaScript エンジンなどの他のランタイムが採用するさまざまなアプローチには類似点があるのではないかと思います。

Raymond Chen はブログ投稿を書き、解放しようとしている歩行記憶がパフォーマンスに悪影響を及ぼす可能性があることを指摘しました。コンテキストは、アプリケーションのシャットダウン時にメモリを手動で解放することでした。ブロックはディスクにスワップされている可能性があるため、参照をトラバースする行為により、それらのブロックがスワップインされる可能性があります。この場合、プログラムは、使用可能としてマークされ、そのまま放置されたブロックのトラバースを実行しています。

そのため、OS が一部のブロックをスワップ アウトした可能性がある状況では、ガベージ コレクターを「支援」する行為は、特に寿命の長いオブジェクトに対して、処理速度を低下させる可能性があります。

また、スワップアウトを心配するほど十分なデータが生成されていない場合、合理的なガベージ コレクターが気付くのに十分な時間はかかりません。

そのため、努力する価値はなく、逆効果になる可能性があります。ヒープ「ドミネーター」への参照を削除することはおそらく理にかなっていますが。これらは、収集された場合、他の多くのオブジェクトの収集を可能にするオブジェクトです。そのため、コレクション内の各項目ではなく、コレクション自体への参照を削除してください。

于 2012-12-20T19:52:42.270 に答える
3

非常に賢い人々は、これらのガベージ コレクション モデルに懸命に取り組んできました。あなたが行うことは、彼らが実装したものよりも大幅にパフォーマンスを向上させる可能性が比較的低い.

ガベージ コレクションが大きなコストになっている場合は、ガベージ コレクションが必要なオブジェクトの数を減らすことに集中した方がよいでしょう (オブジェクト プール パターンを検討してください) 。

于 2012-12-20T19:33:03.587 に答える