共通の JVM パラメータ設定と GC パフォーマンスの最適化

共通の JVM パラメータ設定

ガベージ コレクションの統計

-XX:+PrintGC GC 概要情報を印刷
-XX:+PrintGCDetails GC 詳細情報を印刷
-XX:+PrintGCTimeStamps CG 発生のタイムスタンプを印刷
-Xloggc:log/gc.log GC ログの場所を指定してファイルとして出力
-XX: +PrintHeapAtGC 各 GC の前後にヒープ情報を出力します。

ヒープ設定

-Xms: 初期ヒープサイズ、最小ヒープ
-Xmx: 最大ヒープサイズ
-Xmn: 新しい世代のサイズを設定
-XX: NewRatio 新しい世代と古い世代の比率。3 の場合は、新しい世代の比率を意味します。若い世代と古い世代は 1:3 で、若い世代は全体の若い世代の合計の 1/4 を占め、古い世代は
-XX:SurvivorRatio で 2 つの Survivor エリアの eden に対する比率を設定します。Survivor エリアが 2 つあることに注意してください。例: 8 は、エデンを意味します: Survivor=8:2、Survivor 領域は若い世代全体の 1/10 を占めます
-XX:PermSize: 永続領域の初期スペースを設定します。
-XX:MaxPermSize: 永続領域の最大スペースを設定します。常設エリア。
-XX:+MaxTenuringThreshold=10: 新しい世代のガベージの最大存続期間。これは、オブジェクトが Survivor 領域に 10 回コピーされた後に古い存続期間に入るという意味です。0 に設定すると、若い世代のオブジェクトは Survivor 領域を経由せずに直接古い世代に入ります。
-XX:+PretenureSizeThreshold: 大きなオブジェクトが直接古い時代に入るしきい値を設定します。オブジェクトのサイズがこの値を超える場合、古い世代に直接割り当てられます。 

スタック割り当てパラメータ

-Xss: スタック領域のサイズを設定します。

ガベージコレクターの設定

シリアルコレクターの設定

-XX:+UseSerialGC: シリアル コレクターを設定します。これは通常、小規模なアプリケーションや単一プロセッサに適しています。アルゴリズムは比較的単純で、GC 効率は高くなりますが、アプリケーションが一時停止する可能性があります。

並列収集コレクターの設定 (ParallelGC コレクターの目標は、管理可能なスループットを達成することです)

-XX:+UseParNewGC: 並列収集の若い世代を設定します。
-XX:+UseParallelGC: 若い世代が並列コレクション コレクターを使用するように設定します。複数のスレッドが GC を並行して実行します。これは一般にマルチプロセッサ システムに適用でき、GC の効率を向上させることができますが、アルゴリズムが複雑でシステムの消費量が多くなります。
-XX:+UseParalledlOldGC: Java1.6以降にのみ登場した並列リサイクルコレクタとして古い世代を設定します。
-XX:ParallelGCThreads=n: 並列コレクターが収集に使用するスレッドの数を設定します。CPU の数と同じであることが望ましいです。
-XX:MaxGCPauseMillis=n: 若い世代の各並列ガベージ コレクションの最大一時停止時間を設定します。
-XX:GCTimeRatio=n: プログラム実行時間に対するガベージ コレクション時間の割合を設定します。式は 1/(1+n)
-XX:+UseAdaptiveSizePolicy: アダプティブ ポリシーで、若い世代領域のサイズと対応する Survivor 領域の比率が自動的に選択されます。

CMS 同時コレクタ (最短の一時停止を目標とする)

-XX:+UseConcMarkSoupGC: CMS メモリ コレクションを使用します。
-XX:+ParallelCMSThreads: CMS スレッドの数を設定します。 
-XX:CMSFullGCsBeforeCompaction: CMS がメモリ圧縮を実行する回数。コンカレント コレクタはメモリ空間の圧縮と整理を行わないため、一定期間実行すると「断片化」が発生し、動作効率が低下します。
-XX:+UseCMSCompactAtFullCollection: FULL GC 中の古い世代の圧縮。CMS はメモリを移動しないため、断片化が非常に起こりやすく、メモリ不足が発生するため、この時点でメモリ圧縮が有効になります。パフォーマンスに影響を与える可能性がありますが、断片化は解消されます。
-XX:+CMSInitiatingOccupancyFraction: 古い時代のスペースが使用された後に CMS コレクターがトリガーされるように設定します。デフォルトは 68% です。 
-XX:+CMSClassUnloadingEnabled: クラス メタデータのリサイクルを許可します。
-XX:+CMSParallelRemarkEndable: 並列リマークを有効にします。 
-XX:CMSInitatingPermOccupancyFraction: 永続領域の占有率がこのパーセンテージに達すると、CMS リカバリを開始します (-XX:+CMSClassUnloadingEnabled がアクティブ化されている場合)。 
-XX:UseCMSInitatingOccupancyOnly: しきい値に達した場合にのみ CMS リサイクルが実行されることを示します。 
-XX:+CMSIncrementalMode: 単一 CPU により適したインクリメンタル モードを使用します。 

G1コレクター

-XX:+UseG1GC: G1 コレクターを使用します。 
-XX:+UnlockExperimentalVMOptions: 実験的なパラメータを許可します。 
-XX:+MaxGCPauseMills: ガベージ コレクションの最大一時停止時間を設定します。 
-XX:+GCPauseIntervalMills: 一時停止間隔を設定します。 

JVM の GC パフォーマンスの最適化

GC パフォーマンスには主に 2 つの指標があります。スループット (作業時間はカウントされず、合計時間に対する GC 時間の比率) と一時停止時間です。

ヒープサイズ

デフォルトでは、VM は、MinHeapFreeRatio と MaxHeapFreeRatio で指定される VM 全体の空き領域の比率を維持するためにヒープ サイズを増減します。

一般に、サーバー側のアプリには次のルールがあります。

(1) できるだけ多くのメモリを vm に割り当てます;
(2) Xms と Xmx を同じ値に設定します。仮想マシンの起動時に使用されるメモリが比較的小さく、この時点で多くのオブジェクトを初期化する必要がある場合、仮想マシンは繰り返しメモリを増やす必要があります。
(3) プロセッサコアの数が増加すると、メモリも増加します。

若い世代

(1) プログラムのスムーズな動作に影響を与える要因は、新しい世代のサイズです。若い世代が大きくなるほどマイナー コレクションは少なくなりますが、ヒープ サイズが固定されている場合は、若い世代が大きくなり、古い世代が小さくなり、メジャー コレクションが増えます。
(2) 8NewRatio は、新世代と旧世代のサイズ比を反映します。NewSize と MaxNewSize は若い世代のサイズの下限と上限を反映しており、この 2 つの値を同じに設定すると、若い世代のサイズが固定されます (Xms と Xmx と同じ)。
(3) SurvivorRatio も Survivor のサイズを最適化できますが、これはパフォーマンスにはほとんど影響しません。SurvivorRatio は、Eden と Survivor のサイズ比です。

一般に、サーバー側のアプリには次のルールがあります。

(1) まず、VM に割り当てることができる最大ヒープ サイズを決定し、次に、最適な若い世代のサイズを設定します。(2)
ヒープ サイズが固定されている場合、若い世代のサイズを増やすことは、古い世代のサイズを減らすことを意味します。世代。古い世代を、存続するすべてのオブジェクトをいつでも保持できる十分な大きさにします (10% ~ 20% を空けておきます)。

若い世代のサイズ選び

(1) 応答時間優先の適用:システムの最小応答時間制限に近づくまで、できるだけ大きな値に設定します (この場合、若い世代の収集頻度も最小になると同時に、古い世代に到達するオブジェクトの数を減らします。
(2) スループット優先のアプリケーション: 応答時間の要件がなく、ガベージ コレクションを並行して実行できるため、可能な限り大きく設定し、Gbit レベルに達する可能性があります。これは、一般に 8 を超えるアプリケーションに適しています。 CPU。
(3) 小さすぎる設定は避けてください。新しい世代の設定が小さすぎると、①YGC 倍の頻度が発生し、②YGC オブジェクトが直接古い世代に入る可能性があり、この時点で古い世代がいっぱいの場合、FGC がトリガーされます。

旧世代のサイズ選択

(1) 応答時間を優先するアプリケーション: 旧世代はコンカレント コレクターを使用します。ヒープ設定が小さい場合は、メモリの断片化、高いリサイクル頻度、およびアプリケーションの停止が発生する可能性があるため、従来のマーク アンド スイープ方式が使用されますが、ヒープが大きい場合は、収集に時間がかかります。
         一般に、同時ガベージ コレクション情報、永続世代の同時コレクション数、従来の GC 情報、および若い世代と古い世代のコレクションに費やされた時間の割合のデータを参照する必要があります
(2) スループットを優先するアプリケーション: 一般に、スループットを優先するアプリケーションには、大きな若い世代と小さな古い世代があり、ほとんどの短期オブジェクトを可能な限りリサイクルし、中期オブジェクトを削減できます。古い世代では、存続期間の長いオブジェクトのみが保存されます。

ヒープが小さいことが原因で発生する断片化の問題

CMS 旧世代の同時コレクタはマークアンドスイープ アルゴリズムを使用するためヒープを圧縮しませんコレクターが再利用するとき、隣接するスペースをマージして、より大きなオブジェクトに割り当てられるようにします。ただし、ヒープ領域が小さい場合、一定時間実行すると「断片化」が発生します。コンカレント コレクターが十分な領域を見つけられない場合、コンカレント コレクターは停止します。次の構成が必要になる場合があります。

-XX:+UseCMSCompactAtFullCollection: 同時コレクターを使用する場合、古い世代の圧縮をオンにします。
-XX:CMSFullGCsBeforeCompaction=0: 上記の設定が有効な場合、古い世代を圧縮するためのフル GC の回数がここで設定されます。

その他の指示

(1) 64 ビット オペレーティング システムでは、Linux 上の 64 ビット jdk は 32 ビット jdk よりも低速ですが、より多くのメモリとスループットを消費します。

(2) XMX と XMS の設定は同じサイズであり、MaxPermSize と MinPermSize の設定も同じサイズであるため、ヒープ サイズのスケーリングによってもたらされる圧力を軽減できます。

(3) CMS の目標は GC 一時停止時間を最短にすることです。CMS を使用する利点は、使用する若い世代をできるだけ少なくし、古い世代が CMS を使用して並行して収集することで、システムのスループット効率を確保できることです。低遅延で

(4) システムが停止した場合、GC の問題かプログラムの問題である可能性があります。jmap と jstack を使用して確認するか、killall -3 java を実行して Java コンソール ログを確認すると、多くの問題が確認できます。

(5) キャッシュを使用する場合は、古い世代の方が大きく、キャッシュされた HashMap の長さは無制限ではなく、キャッシュには LRU アルゴリズムを使用することをお勧めします。LRUMap の最大長もそれに応じて設定する必要があります。実際の状況に。

(6) 同時リサイクルを使用する場合、若い世代は小さく、古い世代は大きくなります。古い世代は同時リサイクルを使用するため、時間がかかっても他のプログラムの実行には影響せず、Web サイトは継続的に実行されます。止まらない

(7) JVM パラメータの設定 (特に –Xmx –Xms –Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold などのパラメータの設定) には決まった計算式はなく、実際の JVM のデータに応じて測定する必要があります。 PV旧エリア、YGC数など。昇格の失敗を避けるために、xmn 設定が小さすぎる可能性があります。これは、YGC の数が増加し、同時アクセスを処理する能力が低下することを意味します。各パラメータの調整には、特定のアプリケーションに最適な構成を見つけるための詳細なパフォーマンス テストが必要です。

昇格に失敗しました: (昇格に失敗しました)

ガベージ コレクション中に昇格に失敗しました。一般に、理由は 2 つ考えられます。1 つ目の理由は、To survivor スペースが十分ではなく、スペース内のオブジェクトを古い世代に移動すべきではないが、若い世代に多くのオブジェクトが存在することです。スペースをサルベージします。2 番目の理由は、古い世代には若い世代からのオブジェクトを受け入れるのに十分なスペースがないためです。どちらの場合も、フル GC になり、Web サイトが長時間停止します。時間。

解決:

  • 最初の理由の解決策は、レスキュー スペースを削除することです。 -XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0 を設定するだけですが、レスキュー スペースが使用されないため、古い世代がいっぱいになりやすく、フル GC が発生します。実行頻度が高くなるので、昇格に失敗することがなくなるようにレスキュースペースを増やすことができます。
  • 2 番目の理由に対する私の解決策は、CMSInitiatingOccupancyFraction を特定の値 (70 と仮定) に設定して、古い世代のスペースが 70% に達し、古い世代に若い世代からのオブジェクトを受け入れるのに十分なスペースがあるときに CMS が実行を開始するようにすることです。 。

実際のプログラミングにおけるパフォーマンスの最適化

実際にプログラムを書く上で注意すべき点は以下のとおりです。これらの習慣を身につけることで、無駄なメモリの消費をある程度減らすことができ、メモリ不足による継続的な GC をさらに減らすことができます。

(1) 新規オブジェクトを減らす。新しいオブジェクトを作成するたびに、新しいメモリ空間を開く必要があります。これらのオブジェクトが参照されなくなったら、リサイクルする必要があります。したがって、オブジェクトを合理的に最大限に再利用するか、オブジェクトの代わりに基本データ型を使用すると、メモリの節約に役立ちます (2) より多くのローカル変数を使用し、静的変数の使用を減らします
ローカル変数は、高速アクセスのためにスタック上に作成されます。静的変数はヒープ メモリ内にあります。
(3) GC に多大な負担がかかるため、finalize の使用は避けてください。
(4) シングルスレッドの場合は、スレッド セーフは同期によって得られるため、非マルチスレッド セーフを使用するようにしてください。同期メカニズムによりパフォーマンスが低下する可能性があります。たとえば、シングルスレッド プログラムで HashMap を使用できる場合は、HashTable を使用しないでください。同様に、同期の使用を最小限に抑えます。
(5) 乗除記号をシフト記号に置き換えます。例: a*8 は a<<3 として記述する必要があります
(6) 頻繁に使用されるオブジェクトにはキャッシュを使用します
(7) パッケージ化タイプの代わりに基本タイプを使用し、2 次元配列の代わりに 1 次元配列を使用するようにしてください。 ;
(8) Final 修飾子を使用してみる、final は変更できないことを意味し、アクセス効率が高い;
(9) シングルスレッド (またはローカル変数の場合) の場合、文字列には StringBuilder を使用してみるStringBuffer より高速です。
(10) String が遅いのはなぜですか? String は不変オブジェクトであるため、String 型が変更されるたびに、実際には新しい String オブジェクトを生成し、新しい String オブジェクトへのポインタを指すのと同じになります。スレッドの安全性が保証できない場合は、StringBuffer を使用して文字列を連結してみてください。なお、StringBuffer のデフォルトのキャッシュ容量は 16 文字であり、16 文字を超える場合は、append メソッドでプライベートの ExpandCapacity() メソッドを呼び出してキャッシュ容量を確保します。したがって、StringBuffer の容量をあらかじめ設定できる場合は、追記による容量拡張は避けてください。スレッドの安全性を保証できる場合は、StringBuilder を使用してください。

おすすめ

転載: blog.csdn.net/vcit102/article/details/131800172