CMSとG1ガベージコレクターを理解するためにステップバイステップで

新世代と旧世代の間でガベージコレクションアルゴリズムが異なる理由

新世代で。ガベージコレクションで多数のオブジェクトが停止し、少数のオブジェクトのみが存続することが検出されるたびに、レプリケーションアルゴリズムが選択され、少数の存続するオブジェクトのレプリケーションコストを支払うだけでコレクションを完了できます。老後は、オブジェクトの生存率が高いため、それを保証するための余分なスペースがないため、リサイクルには「マーククリア」または「マークソート」アルゴリズムが必要です。

 

ガベージコレクター間の関係

image.png

図の上は新世代のガベージコレクター、下は旧世代のガベージコレクターです。接続は併用できます。最高のガベージコレクターはありません。最も適切なものだけが妥当です。

 

シリアル/シリアルオールド

JVMが最初に生まれたときに存在した最も古いガベージコレクター。この機能はシングルスレッドで、排他的で、シングルCPUに適しており、通常はクライアントモードで使用されます。

この種のガベージコレクターは、数十メガバイトから100メガバイトまたは200メガバイトのヒープスペースのガベージコレクションにのみ適しています。(休止時間は約100msで制御できます)。このメモリサイズを超えると、回復速度が非常に遅くなります。そのため、このガベージコレクターは今では味のないものになっています。(実際には、CMSの代わりとして一般的に使用されます)

image.png

シリアルガベージコレクタは、動作中のパラメータ設定により、新世代、旧世代で使用できます。

 

パララー(平行)スカベン/パララーオールド

効率を上げるために、JDK1.3から始めてください。JVMは、マルチスレッドのガベージコレクションメカニズムの使用を開始しました。スループットに重点を置くガベージコレクターの場合、高スループットはCPU時間を効率的に使用して、プログラムのコンピューティングタスクをできるだけ早く完了することができます。これは主に、バックグラウンドでの相互作用があまりないタスク、つまりCPUを集中的に使用するタスクに適しています。(拡張:CPUが集中データ操作を実行する場合、CPUを集中的に使用し、CPUがIOの読み取りおよび書き込み操作の待機にほとんどの時間を費やす場合、IOを集中的に使用します。注:IOを集中的に使用するのは、主にハードディスクで機能します。 。したがって、メカニカルハードドライブとソリッドステートドライブの違いについて詳しく知ることができます

スループット:いわゆるスループットは、CPUがコードの実行に費やす時間とCPUが消費する時間の比率です。つまり、スループット=ユーザーコードの実行時間/(ユーザーコードの実行時間+ガベージコレクション時間)です。これは、暴力的な手段でSTWを処理するのに費やした時間に相当し、基本的に最適化されていませんが、良好な結果が得られています。仮想マシンは合計100分間実行され、そのうちガベージコレクションには1分かかるため、スループットは99%になります。もう1つ覚えておくべきこと:今日はお母さんから8時間勉強するように言われ、30分勉強して、携帯電話で1時間半遊んでいます。8時間経過したら、お母さんにお母さんと言いました。!終了しました!" 、実際のスループット量は非常に少ないです。要するに、私たちは集中力を理解することができます)。

ガベージコレクタは、ヒープスペースで100メガバイトから数ギガバイトのメモリを再利用するのに適しています。

image.png

実行時に、パラメーター設定を使用して、新世代と旧世代が並列(マルチスレッド)ガベージコレクターを使用するようにすることができます。

 

-XX:MaxGCPauseMillis

このパラメータは、STWの一時停止時間をアクティブに設定できます。ただし、このパラメータ値を小さい値に設定すると、ガベージコレクションが高速になるわけではありません。ガベージコレクションの一時停止時間は、スループット(ガベージコレクションが頻繁になる)と新世代のスペースを犠牲にして短縮されます。新世代のスペースが小さくなると、ガベージコレクションのトリガーが頻繁になり、ガベージコレクションの処理頻度が高くなるため、各STWの時間が短縮されます。しかし、各スタートアップにも時間がかかります。したがって、ガベージコレクションを頻繁に行うと、スループットが低下します。したがって、マルチスレッドのガベージコレクタでは、この値をデフォルトに設定できます。このパラメーターは、主にG1ガベージコレクターがサービスを実行するためのものです。

 

-XX:+ UseAdaptiveSizePolicy

このパラメーターはデフォルトでオンになっています。パラメータがアクティブになっている場合、新しい世代のサイズ、Edenの比率、およびSurvivorを割り当てるためにtopを手動で設定する必要はありません。老後のオブジェクトサイズなどの詳細なパラメータがプロモートされています。仮想マシンは、現在のシステム操作に基づいてパフォーマンス監視情報を収集します。これらのパラメータは動的に調整され、最適な一時停止時間または最大スループットを提供します。

 

ParNew

CMSと連携するマルチスレッドガベージコレクタ。CMSの場合、古い世代自体を収集し、ペアになっている新しい世代のガベージコレクターにはSerialオプションとParNewオプションがあります。ParNewとParallerScavenは基本的に同じ、マルチスレッド、マルチCPUであり、シリアルよりも一時停止時間が短くなっています。

 

CMS(ConcurrentMark Sweep)

注:ここには、古いCMSガベージコレクターのプロセスのみが含まれています。

image.png

Cmsガベージコレクターは、最短の一時停止時間を取得することを目的としたガベージコレクターです。現在、JAVAアプリケーションの大部分はインターネットまたはB / Sシステムのサーバー側に集中しています。このタイプのアプリケーションは、サービスの応答速度に特別な注意を払い、ユーザーにより良いエクスペリエンスを提供するために、システムの一時停止時間が最短で、システムの一時停止時間が最短であることを望んでいます。CMSコレクターは、「マークスイープ」アルゴリズムに基づいて実装されます。その操作プロセスは、以前のタイプのコレクターよりも複雑です。それは4つのステップに分かれています。

CMSガベージコレクションの4つのステップ

イニシャルマーク

短時間、GCルートが直接関連付けることができるオブジェクトにマークを付けるだけです。高速。(これの目的はガベージを割り当てることです。新しいGCルートは、最初のマーキング後のプロセスで生成されます。これはすでに参照チェーンに対応していますが、後続の参照によって生成されたガベージは次のガベージコレクション用に予約されています)。

コンカレントマーク

より長く、同時にユーザースレッド。GCRootsに関連付けられているすべての到達可能オブジェクトをマークします(初期マーキング)。ここでの時間は比較的長いので、並行処理を採用しています。

リマーク

短時間、同時マーク中のユーザーの操作継続により変化するオブジェクト部分のマーク記録を修正するため。この段階での一時停止時間は、最初のマーキングよりもわずかに長くなりますが、同時マーキング時間よりもはるかに短くなります。ここで初めて学ぶ多くの友達は戸惑うかもしれません。(とにかく、私はそれを初めて理解しませんでした、そして私が今それを理解したかどうかはわかりません)。まず、ユーザースレッドとGCスレッドが同時に実行されるとどうなりますか?ガベージをマークするとき、GCスレッドはそれ自体のスレッドにもシリアルです。つまり、すでにマークされているオブジェクトの参照が変更された場合、マーク付けプロセス中に戻って処理することはできません。

さて、2つの状況があります:ユーザースレッドは、GCスレッドが生きているとマークしたオブジェクトをデッドとしてマークします。この時点で何が起こりますか?答えは、GCスレッドはこの実際の死んだオブジェクトのこの波を処理せず、しばらく存続させ、次のガベージコレクションが処理するまで待つということです。これが私たちがフローティングガベージと呼んでいるものです。

次に、別のタイプがあります。GCスレッドはそれをガベージとして扱いますが、このオブジェクトは、GCスレッドによって存続していると判断された他のオブジェクトによって再参照されます。この時点で、到達可能性分析によると、オブジェクトはガベージではありませんが、同時マーキングを実行し続けるGCスレッドによって復活としてマークすることはできません。現時点では、これらの復活したオブジェクトは、死んだオブジェクトとしてリサイクルされる可能性があります。では、この問題を回避する方法は?対処するには、再度マークを付ける必要があります。

要するに、同時マーキングは正しい生きたゴミの90%または99をマークします。再マーキングとは、「医師が患者を火葬する」前に患者が完全に死んでいるかどうかを再確認すること、つまり、私たちが再び生きることを逃した復活のゴミにマークを付けることです。それで、具体的にどのようにそれをするか、次の記事は3色のマークを逃す問題と解決策に言及します。

同時クリーンアップ

マーキング全体で同時マーキングと同時削除プロセスが最も長いため、ガベージコレクションスレッドとユーザースレッドは連携して機能します。そのため、一般的に、CMSコレクタのメモリ回復プロセスはユーザースレッドと同時に実行されます。

明らかに、このプロセスは比較的長いです。CMSを使用すると、この比較的長いGC作業をユーザースレッドと並行して実行できます。誰もが「スループットに焦点を合わせた」ガベージコレクターとして歓迎されるのは、まさにこのステップのおかげです。明らかに、これによりSTW時間が大幅に短縮されますが、そうすることの代償は何ですか?

不利益

CPUに敏感

Cmsはプロセッサリソースに非常に敏感です。結局のところ、Cmsは同時収集と同時リサイクル(ユーザーマルチスレッド+ GCスレッド)を使用します。したがって、コアの数がスレッドの数より少ない場合、ユーザーへの影響は大きくなります。同時マーキングと同時クリアの場合、追加されたGCスレッドにより、CPUはより多くのタスクを実行します。CPUの実行では、スレッドの数がCPUコアの数よりも多い場合、CPUはコンテキストの切り替えを頻繁に開始して、同時実行の効果を実現します。しかし、コンテキストスイッチは必然的にプログラムの実行速度に影響を与えます。

 

浮遊ゴミ

CMSの同時クリーンアッププロセスにより、ユーザースレッドは引き続きガベージを生成します。この時点で生成されたガベージは、マークが付けられていないため、クリアされません。したがって、ガベージのこの部分は、次のガベージコレクションと再マーキングおよびクリアまでしか残せません。この種のゴミは「フローティングゴミ」と呼ばれます。

実際、浮遊ゴミについての公式の言葉の多くは、私たちが理解するのは簡単ではありません。実際、フローティングガベージの収集が容易でない理由は、同時マーキングフェーズで、ユーザースレッドとGCスレッドが同時に実行されるためです。GCスレッドが特定の瞬間にオブジェクトを確認すると、ルートに到達可能になり、ユーザースレッドは次の瞬間に到達可能性チェーンを切断します。現時点では、GCスレッドがこのオブジェクトを振り返ってガベージとして識別することは困難です。これは浮遊ゴミです。しかし、浮遊ゴミは実際のリサイクルにはほとんど影響しません。したがって、次のガベージコレクションに任せてください。

予約スペース

ユーザースレッドとGCスレッドは並行して発生するためです。ガベージがGCによってマークされると、ユーザースレッドはガベージを生成し続けます。したがって、一部のメモリをそれらのために予約する必要があります。また、CMSガベージコレクターは、他の旧世代のコレクターと同様に、ガベージコレクションをトリガーする前に旧世代がほぼ完全に占有されるまで待機できないことも意味します。JDK1.6バージョンでは、旧世代のスペース使用量のしきい値(92%)。

予約スペースが不足している場合、並行モード障害が発生します。このとき、仮想マシンは一時的にSerialOldがCMSを置き換えることを有効にします。(ユーザースレッドを一時停止しますが、ポストシングルスレッドの古いガベージコレクターのみを開始します。CMSはいつでもマルチスレッドの古い古いガベージコレクターからの距離を維持します。あなたなしで)。

 

スペースデブリが発生します

CMS専用のマーク削除アルゴリズムは、ガベージフラグメントを生成します。

想像できます。プログラムがどんどん長くなるにつれて、老後の記憶はますます混沌とします。このとき、フルGCの頻度はどんどん高くなります。これは明らかに、サーバーの長期的な安定した運用とは反対です。

最大の問題は、CMSで使用されるマーク除去アルゴリズムがメモリの断片化を引き起こすことです。メモリが断片化されると、大きなオブジェクトの割り当てに多くの問題が発生します(結局のところ、連続したスペースを占有します)。この問題を解決するために、CMSはパラメーター-XX:+ UseCMSCompactAtFullCollectionを提供します。これは通常有効になっています。ラージオブジェクトを割り当てることができない場合、メモリはデフラグされます(マークデフラグアルゴリズムを使用)。

image.png

マーキングとソートのためのCMSの代わりに、最も原始的なSerialOldガベージコレクターです。また、CMSの使用シナリオは、多くの場合、大容量のメモリ(数十ギガバイト)を備えたサーバーであるためです。このとき、シリアルオールドの作業効率が想像できます。毎ターン数時間のマーキングとソート時間は、ユーザーには受け入れられません。したがって、初期のCMSアプリケーションのシナリオでは、多くのユーザーが指定しました。サーバーを再起動する前に、サーバーを毎日または数日ごとに再起動する必要があります。

  

CMSの概要

一般に、CMSはJVMによって起動される並行ガベージコレクターであり、非常に代表的なものです。しかし、CMSマーク除去アルゴリズムは、メモリの断片化という深刻な問題を引き起こします。メモリの断片化がパフォーマンスに大きな影響を与える場合でも、CMSはタグの最適化アルゴリズムを使用してFullGC中にメモリを再編成します。しかし、FullGC自体は私たちが避けようとしている問題です(かなり時間がかかり、ラグを引き起こし、ユーザーエクスペリエンスに影響を与える可能性があります)。スペースデブリが大きな物体に遭遇した場合、FullGCが事前に実行される可能性があります。したがって、デフォルトのCMSであるバージョンはありません。

拡張:タグソートアルゴリズムを使用しないのはなぜですか

CMSでは、ゴミが同時に削除されるためです。ただし、タグを整理するとオブジェクトのアドレスが変更され、参照に影響を与えるため、ユーザースレッドの通常の操作が破壊されます。

このコレクターは、数Gから20Gのヒープメモリを回復するのに適しています。サーバーのガベージコレクターになることができます。

上手。大容量メモリサーバーのガベージコレクションが長期的で安定したプロセスを維持し、優れたユーザーエクスペリエンスを維持できるようにするにはどうすればよいですか?

 

G1(ガベージファースト1)

デザインのアイデア

JVMのメモリの増加に伴い。STWの時間は、JVMが解決する緊急の問題になっています。従来の世代モデルに従うと、STWの予測不可能性から逃れることはできません。(ゴミの除去は常に次々と波になります)。

STWの時間予測可能性を実現するには、まず考え方を変える必要があります。G1は「ヒープメモリをゼロに変換」し、ヒープメモリを同じサイズの複数の独立した領域(領域)に分割します。各領域は、エデン領域、サバイバー領域、老齢領域、またはさらに広い領域として機能できます。必要に応じて新世代。オブジェクト領域。コレクターは、さまざまな戦略を使用して、さまざまな役割を果たす地域を処理できます。このようにして、新しく作成されたオブジェクトであろうと、一定期間存続した古いオブジェクトであろうと、複数回のリサイクルで存続した古いオブジェクトに対して良好な収集効果を得ることができます。

あなたがインタビューしていて、「パーツに分割する」という考えを言うだけなら、インタビュアーはあなたが専門家であることを知るでしょう。

領域

地域はエデン、サバイバー、または大きなオブジェクトを保管するための特別なタイプの巨大なエリアである可能性があります。G1は、オブジェクトのサイズがリージョンのサイズの半分を超えている限り、大きなオブジェクトと判断できると考えています。そして、リージョン全体の容量を超える超大型オブジェクトは、N個の連続するHumobgousリージョンに格納されます。ほとんどの場合、G1がリサイクルされると、巨大な地域は古い世代の一部として扱われます。

image.png

パラメータ設定

パラメータを開く

-XX:+ UseG1GC

リージョンはサイズに依存します

-XX:+ G1HeapRegionSize

通常、この値を徐々に増やすことをお勧めします。サイズが大きくなると、ガベージはより長く存続し、GC間隔はより長くなります。しかし、GC時間が長くなるたびに

 

最大GC休止時間

MaxGCPauseMillis

このパラメータは重要です。このパラメーターは前述のマルチスレッドガベージコレクターParallerScaven / Paralleler oldで設定できると前述しましたが、Paraller Scaven / Paralleler oldでこのパラメーターを設定しても、基本的に効果がないか、逆効果になります(本当の意味でのGC時間。最大休止時間を短縮すると、新世代のスペースを削減することしかできません。3Mスペースでのガベージコレクションは5Mよりも確実に高速です。しかし、欠点は明らかであり、明らかにスピードアップします。 GC。周波数。スループットが低下します)。

G1は、このパラメーターの制御可能性を追求しているように見えました。ガベージコレクションの一時停止時間を制御するG1の機能の鍵は、各リージョンのリサイクル値を追跡する必要があることです。各リージョン内のガベージオブジェクトの数を知る必要があります。このリージョンがリサイクルされる場合、どのくらいの時間が消費されますか。 。限られた時間内により多くのガベージオブジェクトを収集し、開発で指定された時間範囲内でガベージコレクションによって発生するSTW時間を制御します。

次の図に示すように、3つのSTWの合計時間は、設定したMaxGCPauseMillis内で可能な限り制御されます。また、設定したMaxGCPauseMillis値は、理論的には行き詰まりを感じさせないため、サーバーの長期的な安定した動作を保証し、ガベージコレクションのメモリサイズの制限を打ち破ることができます。

作業工程

image.png

G1の実行プロセスは、大きく4つのステップに分けることができます。

イニシャルマーク

次のGCルートを直接関連付けることができるオブジェクトにマークを付け、TAMSポインターを変更して、ユーザースレッドの次のステージが同時に実行されるときに、使用可能なリージョンに新しいオブジェクトを正しく割り当てることができるようにします。この段階ではSTWが必要ですが、非常に高速であり、マイナーGCの助けを借りて同期的に実行されます。したがって、G1コレクターのこの段階で追加の一時停止はありません。

TAMSとは何ですか?

この一節は私自身の理解です。まず、マーク除去アルゴリズムまたはマークソートアルゴリズムのいずれかを使用しています。オブジェクトグラフのトラバーサルが一貫したスナップショットで実行されるようにする必要があります。このスナップショットはSTABスナップショットにいくぶん似ていますが、その実際の機能は、最初のマークを作成するときにトラバースする必要があるオブジェクトグラフ全体を確認することです。したがって、GCがガベージを収集する場合、新しく追加されたGCルートと新しく追加されたオブジェクトはこのGCのスコープに含まれず、すべてが次のGCの処理に残されます。データを分離することをお勧めします。そうすれば、ラベルの欠落の問題が灰色から白への参照チェーンの破損である必要がある理由を後続の3色のマークに納得させることもでき、他のラベルを受け取ったときにラベルの欠落と見なされます。スキャンされた黒い参照。そして、白いオブジェクトから白いオブジェクトへの参照チェーンが壊れて黒いオブジェクトに接続されているかどうかはカウントされません(ブロガーのように額を壊す読者が​​いるかどうかはわかりません。本や他のブログでは当然のことと考えられています) 。

上記はすべて予兆であり、TAMSは、このGCプロセスの同時マーキング中にユーザースレッドの新しく追加されたオブジェクトを除外するG1の手段です。G1は、リージョンごとにTAMSという名前の2つのポインターを設計しました。スペースの一部は、同時収集プロセスで新しいオブジェクトを記録するためにリージョン領域から分割されます。それらは生きている必要があり、このGCのスコープに含まれていない必要があると見なされます。

コンカレントマーク

GCルートから始めて、ヒープ内のオブジェクトの到達可能性を分析します。オブジェクトグラフ全体を再帰的にスキャンして、リサイクルするオブジェクトを見つけます。この段階は時間がかかりますが、ユーザープログラムと同時に実行できます。オブジェクトグラフのスキャンが完了すると、参照が同時に変更されるオブジェクトがあります(これは、フローティングガベージと欠落ラベルの問題に分けられます。フローティングガベージについては、この記事で詳しく説明します。欠落ラベルの問題については、次の章で詳しく説明します)。 。

ファイナルマーク(STW)

G1は、STAB(元のスナップショット)を使用して、ラベルの欠落の問題に対処します。

スクリーニングとリサイクル

他のガベージコレクションは同時に収集できます。もちろん、G1も収集できます。しかし、なぜSTWはリサイクルのためにダウンする必要があるのでしょうか。重要なのは、2つの単語をフィルタリングすることです。リージョンデザインが生成された後、各リージョンのリカバリコストが並べ替えられます。このとき、設定した予想STW時間値に応じて、地域セットがリサイクル対象として選択されます。次に、空の領域にリサイクルすることを決定した領域の一部の生き残ったオブジェクトをコピーします。最後に、古いリージョンスペース全体をクリーンアップします。

見て、見て。これはコピーアルゴリズム+タグソートアルゴリズムではありませんか?

また、マーキングと並べ替えのアルゴリズムによってオブジェクトのアクティビティが発生するため、オブジェクトはSTWであり、複数のGCスレッドによって並行して完了する必要があります。

特徴

並列および並行性

G1は、マルチCPUおよびマルチコア環境でハードウェアの利点を最大限に活用し、複数のCPUを使用してSTW時間を短縮できます。また、同時マーキングフェーズでは、ユーザースレッドをGCスレッドと同時に実行できます。

世代別コレクション

他のコレクターと同様に、生成の概念はG1でも保持されています。G1は全体として、「マークソート」アルゴリズムに基づくコレクターですが。ローカル(2つのリージョン間)の観点から、「コピー」アルゴリズムが実装されます。いずれにせよ、これら2つのアルゴリズムは、G1操作中にメモリの断片化の問題がないことを意味します。収集後、通常の使用可能なメモリを提供できるため、長時間の実行に役立ちます。大きなオブジェクトを割り当てても、連続するメモリスペースが見つからないため、フルGCは発生しません。

一時停止時間を追求する

-XX:MaxGCPauseMillisは、ターゲットの最大一時停止時間を指定します。G1はそれ自体を分析して、リサイクル用に設定されたリサイクル可能な領域を取得します。(同時に、G1は一斉にゴミの収集を行うのではなく、指定された時間内に収集します。収集頻度が高くなる可能性はありますが、STW時間が制御可能であるとは基本的に感じられません。毎回)。

使用するシーン

メモリが大きいほど良いです。一般的に、CMSとG1のバランスポイントは6〜8Gです。それからG1の世界があります。

機能にCPU感度が含まれていないのはなぜですか

CMSと比較して、G1では同時削除が1ステップ少なくなっています。(同時クリーニングは、参照関係を変更せずに同時に処理できます)。したがって、CPUはそれほど敏感ではありません。

 

言葉を止めろ

第一世代のガベージコレクター(Serial / Serial Old)をご覧ください。新世代と旧世代の両方がすべてのユーザースレッドを一時停止し、GCスレッドを開始して、ガベージコレクションが完了するまでクリーンアップを開始します。この一時停止は「StopTheWord」と呼ばれます。しかし、このStop The Wordは、ユーザースレッドに非常に悪いエクスペリエンスをもたらします。新世代のエデンエリアがいっぱいになると、ガベージコレクションが必要になります。1時間を使用してエデンエリアを1回占有すると、この時点でコンピューターが5分間応答を一時停止する場合があります。古い世代のガベージコレクションが時間の経過とともにトリガーされる場合(古い世代はデフォルトで新しい世代の2倍のメモリです)、クラス間で直接休憩を取ることができます。これは、初期のJVMのパフォーマンスがC / C ++によって批判された理由の1つでもあります。そのため、JVMチームは、STWに費やす時間をなくすか削減するために懸命に取り組んできました。

おすすめ

転載: blog.csdn.net/weixin_47184173/article/details/109635083