JVM 世代別ガベージコレクションメカニズムとガベージコレクションアルゴリズム

JVM 世代別ガベージコレクションメカニズムとガベージコレクションアルゴリズム

[[433574]]

1. GCとは何か

GC (ガベージ コレクション) ガベージ コレクションは、その名前が示すように、特にガベージをリサイクルするために使用されます。 C/C++ では、メモリを使用する必要があるときは、まず手動でメモリを宣言し、使用後に手動でメモリをリサイクルする必要があります。この 2 つの手順は非常に面倒で、この点で問題が発生することがよくあります。これらはすべて Java で自動的に実行されるため、コードを書くときに無効なデータについて心配する必要はありません。

GC分類

現在主流の仮想マシンのほとんどは、世代別コレクションの理論に基づいて設計されています。仮想マシン内のほとんどのオブジェクトは一時的なものであり、複数のガベージ コレクションを生き延びたオブジェクトはリサイクルが困難になるためです。そのため、理論上のヒープは、新しい世代と古い世代の 2 つの領域に分割されます。前者は主に、生まれてすぐに消滅するオブジェクトを格納し、後者は消滅しにくいオブジェクトを格納します。

1. マイナー GC/ヤング GC: 新世代のみのリサイクルを指します。

2. 旧世代リサイクル(Major GC/Old GC):旧世代のみをリサイクルすることを指します。現在、古い世代をリサイクルするという個別の動作を持つのは CMS ガベージ コレクターだけです。 (メジャー GC の定義は非常に混乱を招きます。古い世代を指すという人もいれば、ヒープ全体のコレクションを指すという人もいます。これは、他の人のシナリオに基づいて決定する必要があります。固定された定義はありません。)

3. フルGC: Javaヒープとメソッド領域全体を収集します(メソッド領域も含まれることに注意してください)

3. ガベージコレクションアルゴリズム

1. コピーアルゴリズム

​ メモリ領域を半分に分割します。メモリの半分が使用されると、生き残ったオブジェクトをメモリ領域の残りの半分に配置します。元のメモリ領域は再利用されます。メモリの断片化領域を考慮する必要はありません。メモリを順番に割り当てるだけです。実装が簡単で、実行も効率的です。

しかし、メモリ使用率が 50% にしかならないという欠点もあるため、JVM では次の解決策があります。

アペルリサイクル

​ Eden 領域の追加。一般的に、メモリ領域は次のように割り当てられます: Eden: 80%、Survivor: 20% (From 10%、To 10%)。Survivor 領域が足りない場合は、割り当て保証のために古い世代が必要になります。

2. マークスイープ

アルゴリズムは、「マーキング」と「クリーニング」の 2 つの段階に分かれています。最初のスキャンでは、リサイクル可能なすべてのオブジェクトをマークする必要があり、2 番目のスキャンでは、最初のステップでマークされたオブジェクトをクリーンアップする必要があるため、効率が少し低くなります。大量のマークされたオブジェクトとクリアリングが必要なため、リサイクル効率はコピーアルゴリズムではありません。ほとんどのオブジェクトが一晩で生まれて死ぬと、マークされたオブジェクトが増え、効率は低くなります。

もう 1 つの大きな問題は、大量のメモリ断片化が発生し、大きなオブジェクトを保存できなくなるため、事前に他のガベージ コレクションをトリガーする必要があることです。

3. マークコンパクト

手順はクリア方法と同じですが、2 番目の手順では、マークの外側にあるすべてのオブジェクトを整理し、すべてのオブジェクトを前方に移動して、これらのオブジェクトの外側にあるメモリ領域を直接クリアします。マーキング方式ではメモリの断片化は発生しませんが、効率は低くなります。

ソート方式とクリア方式の主な違いは、一方がオブジェクトをリサイクルし、もう一方がオブジェクトをソートすることです。また、オブジェクトを移動するには、すべてのビジネス スレッドを一時停止し、すべてのオブジェクトへの参照を更新する必要があります (直接ポインタを調整する必要があります)。

JVM ガベージ コレクター

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

JVM の初期に使用されていたガベージ コレクターは、シングル スレッド、排他的であり、単一の CPU に適していました。

数十~数百メガバイトのヒープメモリにのみ適しており、メモリサイズがこれを超えるとリカバリ効率が大幅に低下するため、現状では役に立ちません。

ストップ・ザ・ワールド(STW)

単一のスレッドがガベージ コレクションを実行する場合、コレクションが完了するまですべてのワーカー スレッドを一時停止する必要があります。この一時停止は「Stop The World」と呼ばれますが、この STW はユーザー エクスペリエンスを低下させます。たとえば、アプリケーションは実行時間ごとに 5 分間一時停止して応答する必要があります。これは、初期の JVM と Java が C/C++ 言語によってパフォーマンスが低いと批判された重要な理由でもあります。そのため、JVM 開発チームは STW 時間を排除または短縮するために懸命に取り組んできました。

2. パラレル/パラレルオールド

​ JVM のリサイクル効率を向上させるために、JDK 1.3 以降、JVM はマルチスレッド ガベージ コレクターを使用します。スループットに重点を置いたガベージ コレクターは CPU 時間をより効率的に使用できるため、プログラムの計算タスクを可能な限り迅速に完了できます。

いわゆるスループットとは、CPU がユーザー コードを実行するために使用する時間と CPU の総消費時間の比率です。つまり、スループット = ユーザー コード実行時間 / (ユーザー コード実行時間 + ガベージ コレクション時間) です。仮想マシンは合計 100 分間実行され、そのうちガベージ コレクションに 1 分かかる場合、スループットは 99% になります。

このガベージ コレクターは、数百メガバイトから数ギガバイトのヒープ スペースを回復するのに適しています。

JVMパラメータ設定

JDK1.8のデフォルトは次の組み合わせです

-XX:+UseParallelGC 新しい世代はParallel Scavengeを使用し、古い世代はParallel Oldを使用します。

-XX:最大GC一時停止ミリ秒

ただし、このパラメータを小さい値に設定するとシステムのガベージ コレクションが速くなると考えるのは気まぐれです。ガベージ コレクションの一時停止時間の短縮は、スループットと新しい世代のスペースを犠牲にして実現されます。システムが新しい世代を小さいサイズに設定すると、300 MB の新しい世代を収集する方が、500 MB の新しい世代を収集するよりも確実に速くなります。ただし、これはガベージ コレクションの頻度の増加に直接つながります。元のコレクション プロセスは、10 秒ごとに 1 回実行され、そのたびに 100 ミリ秒の一時停止がありましたが、現在は 5 秒ごとに 1 回実行され、そのたびに 70 ミリ秒の一時停止があります。一時停止時間は確かに短縮されましたが、スループットも低下しました。

-XX:GC時間比率

-XX:GCTimeRatio パラメータの値は、0 より大きく 100 未満の整数である必要があります。これは、ガベージ コレクション時間と合計時間の比率であり、スループットの逆数に相当します。

たとえば、このパラメータを 19 に設定すると、許容される最大ガベージ コレクション時間は合計時間の 5% (つまり、1/(1+19)) になります。デフォルト値は 99 で、最大 1% (つまり、1/(1+99)) のガベージ コレクション時間が許可されます。スループットと密接に関連しているため、ParallelScavenge は「スループット優先のガベージ コレクター」です。

-XX:+アダプティブサイズポリシーを使用する

-XX:+UseAdaptiveSizePolicy (デフォルトで有効)。これはスイッチパラメータです。このパラメータを有効にすると、新しい世代のサイズ (-Xmn)、Eden 領域と Survivor 領域の比率 (-XX:SurvivorRatio)、古い世代に昇格するオブジェクトのサイズ (-XX:PretenureSizeThreshold) などの詳細なパラメータを手動で指定する必要がなくなります。仮想マシンは、現在のシステムの動作状態に基づいてパフォーマンス監視情報を収集し、これらのパラメータを動的に調整して、最適な一時停止時間または最大スループットを提供します。

3. パーニュー/CMS

パーニュー

マルチスレッド ガベージ コレクターは Parallel に似ていますが、唯一の違いは、複数のスレッドと複数の CPU があり、Serial よりも一時停止時間が短いことです。 (JDK9 以降、ParNew は CMS に統合されました)。

同時マークスイープ (CMS)


このタイプのガベージ コレクターは、最短の回復一時停止時間 (STW) を実現することを目的としています。現在、多数の Java アプリケーションがインターネットや B/S システムのサーバー側に集中しています。このようなアプリケーションは、サービスの応答速度を重視し、一時停止時間を短縮してユーザー エクスペリエンスを向上させることを目指しています。

マークスイープ 名前が示すように、このコレクターはマークスイープ方式を使用します。そして、その手順は以前のものよりも複雑です。

全体的なプロセスは 4 つのステップに分かれています。

初期マーキング: GC ルートに直接関連するオブジェクトのみをマークします。このようなオブジェクトは比較的少なく、マーキングは高速です。

​ 同時マーキング: 最初にマークされたオブジェクトに関連付けられているすべてのオブジェクトをマークします。このようなオブジェクトは多数あるため、同時実行性が使用され、ユーザー スレッドと一緒に実行されます。

​ 再マーキング: 同時マーキング中に変更されたオブジェクトのマーキングを修正します。このプロセスは最初のマーキングよりも少し時間がかかりますが、同時マーキングよりもはるかに高速です。

同時クリーニング: ユーザー スレッドで実行してオブジェクトをリサイクルします。

-XX:+UseConcMarkSweepGC は、新しい世代には ParNew が使用され、古い世代には CMS が使用されることを意味します。

欠点:

CPU 感度: 同時実行テクノロジが使用されるため、プロセッサ コアに対する要求が高くなります。

浮動ガベージ: CMS が同時クリアを実行する場合、同時高速を使用するため、クリア中にユーザー スレッドによって新しいガベージが生成されます。

したがって、リサイクル時には、生成されたガベージを保存するために一定の領域を予約する必要があります (JDK 1.6 で設定されたしきい値は 92%)。

ただし、ユーザー スレッドがすぐにガベージを生成し、予約されたメモリがそれを保持できない場合は、同時モード障害が発生します。この場合、仮想マシンは CMS の代わりに Serial Old を一時的に有効にします。

メモリの断片化: マークアンドスイープ方式が使用されるため、メモリの断片化が発生します。

特徴:

一般的に、CMS は JVM によって生成された最初の並行ガベージ コレクターであるため、依然として代表的なものです。なぜマーク アンド スイープ方式を使用するのでしょうか? CMS を実装する場合、オブジェクトをソートすると、ビジネス スレッドを再度一時停止する必要があるためです。オブジェクトをソートすると、STW 時間が長くなります。STW 時間を追求するために、マーク アンド スイープ方式は使用されません。

しかし、最大の問題は、CMS がマーク アンド スイープ アルゴリズムを使用するため、メモリの断片化が発生することです。断片化が多数ある場合、大きなオブジェクトの割り当てに大きな問題が生じます。この問題を解決するために、CMS は -XX:+UseCMSCompactAtFullCollection というパラメータを提供しており、通常はオンになっています。大きなオブジェクトを割り当てることができない場合は、メモリの断片化プロセスが実行されます。 Serial Old はシングルスレッドなので、ここでは通常 Serial Old が使用されます。そのため、メモリ空間が大きく、オブジェクトが多い場合、これが発生すると CMS がスタックします。

このガベージ コレクターは、数 GB から 20 GB 程度のヒープ領域の回復に適しています。

4. ガーベッジファースト(G1)

G1 ガベージ コレクターの設計コンセプトは、これまでのすべてのガベージ コレクターのコンセプトとは異なります。これまでのガベージ コレクターは世代別に設計されていましたが、G1 ではヒープ全体を 1 つの領域と見なし、同じサイズの独立した領域に分割します。各領域は、必要に応じて Eden、Survivor、および旧世代領域の役割を果たすことができます。物をリサイクルする際には、それぞれの地域の状況に合わせてリサイクルすることができ、効率性が向上します。

地域

前述の通り、各リージョンが異なる役割を果たすことができるほか、旧世代と同様に、特に大きなオブジェクトを保管するために使用される Humongous エリアも存在します。オブジェクトがリージョン スペースのサイズの半分を超えると、大きなオブジェクトと見なされます。 (各リージョンのサイズは、パラメータ -XX:G1HeapRegionSize で設定できます。値の範囲は 1MB ~ 32MB で、2 の累乗にする必要があります。)

リージョン全体の容量を超える超大型オブジェクトは、N 個の連続する Humongous Region に保存されます。ほとんどの場合、G1 リサイクルでは Humongous Region を古い世代の一部として扱います。

パラメータを有効にする: -XX:+UseG1GC `

パーティション サイズ: -XX:+G1HeapRegionSize


一般的に、この値は徐々に増やすことが推奨されます。サイズが大きくなるにつれて、ガベージがより長く存続し、GC 間隔は長くなりますが、各 GC の時間も長くなります。

最大 GC 一時停止時間: -XX:MaxGCPauseMillis

操作プロセス

G1 の操作プロセスは、大きく分けて次の 4 つのステップに分けられます。

初期マーキング: GC ルートに関連付けることができるオブジェクトをマークし、TAMS ポインターの値を変更します。このプロセスではユーザー スレッドを一時停止する必要がありますが、所要時間は非常に短くなります。

TAMS (Top at Mark Start): 次の同時マーキングが実行されると、ユーザー スレッドは新しいオブジェクトを生成し、これらのオブジェクトはガベージではなく存続可能なオブジェクトであると判断されます。このとき、これらのオブジェクトを保存するための小さな領域を割り当てる必要があります。

同時マーキング: リサイクルするすべてのオブジェクトをスキャンしてマークします。スキャンが完了すると、同時に参照が変更されたオブジェクトが存在し、これらのオブジェクトは見逃されます。これらの見逃されたオブジェクトは、SATB アルゴリズムによって解決されます。

SATB (snapshot-at-the-beginning): スナップショットと同様に、現在のエリアのスナップショットが保存され、最終的なマーキング プロセス中に比較され、見逃された項目が再マーキングされます (これについては次の記事で詳しく説明します)。

最終マーキング: すべてのユーザー スレッドを一時停止し、以前に見逃されたオブジェクトをマークします。

ライブデータのカウントと排出:地域の統計を更新し、各地域のリサイクル値をソートし、ユーザーが設定した一時停止時間に基づいてリサイクル計画を策定し、リサイクルする地域を自由に選択できます。リサイクルする必要があるリージョンを空のリージョン領域にコピーし、元のリージョン領域全体をクリアします。これにはオブジェクトの移動も含まれるため、すべてのユーザー スレッドを一時停止し、複数のコレクター スレッドで完了する必要があります。

特徴:

​ 並列性と同時実行性: G1は、マルチCPUおよびマルチコア環境のハードウェアの利点を最大限に活用し、複数のCPU(CPUまたはCPUコア)を使用してStop-The-Worldの停止時間を短縮します。他のコレクター

G1 コレクターは、GC アクションが元々 Java スレッドの実行を一時停止する必要があったとしても、Java プログラムが並行して実行を継続できるようにします。

世代別コレクション: 他のコレクターと同様に、世代の概念は G1 でも保持されます。 G1は他のコレクターの協力なしにGCヒープ全体を独立して管理できるが、異なるアプローチを採用することもできる。

新しく作成されたオブジェクトと、一定期間存続し、複数の GC を生き延びた古いオブジェクトを処理して、より良いコレクション結果を取得します。

​ スペース統合: CMS の「マークスイープ」アルゴリズムとは異なり、G1 は全体として「マークコンパクト」アルゴリズムに基づいて実装され、ローカル (2 つの領域間) では「コピー」アルゴリズムに基づいて実装されたコレクターです。ただし、両方のアルゴリズムにより、G1 は操作中にメモリ空間の断片化を生成せず、コレクション後に通常の使用可能なメモリを提供できます。この機能は、プログラムを長時間実行する場合に役立ちます。大きなオブジェクトを割り当てる場合、連続したメモリ領域が見つからないため、次の GC が事前にトリガーされません。

一時停止時間の追求: -XX:MaxGCPauseMillis は、目標の最大一時停止時間を指定します。G1 は、この目標時間を達成するために、新しい世代と古い世代の比率、ヒープ サイズ、およびプロモーション期間を調整しようとします。

このガベージ コレクターは、数百 GB のヒープ領域を回復するのに適しています。一般的に言えば、G1 と CMS のバランスポイントは 6 ~ 8G です。メモリが大きい場合にのみ、G1 が有利になります。

<<:  銀行は人工知能を導入し、スマートな顧客サービス以上のものを提供している

>>:  トロント大学のデュヴノーチームは確率微分方程式を組み合わせて、無限深ベイズニューラルネットワークを提案した。

ブログ    
ブログ    

推薦する

...

素人の私でも、機械学習コミュニティのこれらの問題が分かります

「分野が違えば意味も違う」とよく言われます。機械学習コミュニティは部外者から見るとどのように見えるの...

...

ChatGPT が処理できない 5 つのプログラミング タスク

ネイト・ロシディ翻訳者 | ブガッティレビュー | Chonglou制作:51CTO テクノロジース...

会話型AIが発展途上国の経済をどう変えるか

テクノロジーは商品の売買方法を変えました。電子商取引の発展により、トレーダーは世界中のほぼどこでも、...

CreditEase の R&D ディレクター、張振氏: 運用・保守ロボットのタスク決定システムの進化

[51CTO.comより引用] 2018年5月18日〜19日、51CTO主催のグローバルソフトウェア...

自己強化型機械学習プロジェクト 10 選

機械学習プロジェクトは大きな発展の可能性を秘めています。最近、韓国の人気ドラマでもこの用語が使用され...

人工知能はゴールドラッシュか?

これはスタートアップの成長を促進するのに最適な活況を呈している市場であり、起業家たちは注目し始めてい...

体験談まとめ VB.NET 暗号化アルゴリズムの分類

家が施錠されていなければ、誰でも勝手に入ることができ、暗号化なしでデータを勝手に変更できてしまうと、...

...

OpenAI の組み込み検索は本当に便利ですか?定量的な評価により、より深い理解が得られます。

ベクターデータベースの強力なライバルが登場するか?トラック関連のスタートアップ企業がまたもや倒産しそ...

...

OpenAIがカスタムコマンド機能を開始、会話ごとに好みや情報を繰り返す必要がなくなる

OpenAIは7月21日、カスタム指示機能のリリースを発表しました。この機能はまずPLUSプランのベ...

人工知能とは何ですか?

人工知能とは何か人工知能(AI)の誕生以来、その定義と意味合いは議論の的となってきました。文字通り、...