JVMパラメータの最適化(基本記事)

過去数日間、実稼働前の環境をテストしたところ、TPSが不安定であることがわかりました。リファクタリングされたシステムであるため、元のシステムは同時実行性が高い場合は問題ないと言われています。その結果、リファクタリングされたシステムは、数十の同時実行によってプレッシャーがかかると、あらゆる種類の不安定になります。テストの同僚は何も言わなかったが、彼は顔を平手打ちされたように感じた。

したがって、さまざまな調査で最初に頭に浮かぶのはJVMパラメーターであるため、良い結果が得られることを期待して最適化しました。不安定の原因は、LoadRunnerがインストールされているストレステストサーバーの不安定性であることが後で証明されましたが、これは私のシステムとは関係ありませんが、これも記録です。1つはバックアップを作成するためのもので、もう1つは他の人の参考になること。

前面に書かれた言葉

Hotspot JDKによって提供されるパラメーターのデフォルト値はマイナーバージョン間で絶えず変化するため、パラメーターは相互に影響を及ぼします。さらに、サーバー構成が異なると、最終結果に影響を与える可能性があります。したがって、インターネット上の特定の記事(これを含む)のパラメーター構成について迷信しないでください。すべての構成は、使用する前に自分でテストする必要があります。JVMパラメータのデフォルト値が絶えず変化することを考慮して-XX:+PrintFlagsFinal、次のような現在の環境のJVMパラメータのデフォルト値印刷java -XX:PrintFlagsFinal -versionするために使用java [生产环境参数] -XX:+PrintFlagsFinal –version | grep [待查证的参数]できます。または特定のパラメータデータ表示するために使用できます。

ここでは8Gサーバのパラメータは、次のようにJDKのバージョン情報は、次のとおりです。

java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)

ヒープ設定

ヒープメモリ設定は、Javaプログラマの基本的な品質と見なす必要があり、少なくともXms、Xmx、およびXmnの3つのパラメータを変更する必要があります。しかし、2GヒープサイズのJVMが合計でどのくらいのメモリを占有する可能性がありますか?

ヒープメモリ+スレッド数*スレッドスタック+永続的な生成+バイナリコード+オフヒープメモリ

2G + 1000 * 1M + 256M + 48 / 240M +(〜2G)= 5.5G(3.5G)-ヒープ
メモリ:Javaオブジェクトを格納し、デフォルトは物理メモリの1/64です-
スレッドスタック:ローカル変数を格納します(アトミックタイプ、リファレンス)など、デフォルトは1Mです-
永続的な生成:ストレージクラスの定義と定数プール、JDK7 / 8の違いに注意してください-
バイナリコード:JDK7と8、マルチレイヤーコンパイルを開くときのデフォルト値は異なります、 48から240Mに
-heap外部メモリ:ネッティー、オフヒープキャッシュなどで使用されるデフォルトの最大値は、ヒープメモリのサイズについてです

つまり、ヒープメモリが2Gに設定されている場合、1000スレッドのJVMは5.5Gを占有する必要があります。システム占有、IO占有などのさまざまな条件を考慮して、8Gサーバーもサービスを開始します。もちろん、スレッドの数が少なく、同時実行性が高くなく、プレッシャーが高くない場合でも、複数のスレッドを開始でき、ヒープメモリを減らすこともできます。

  1. -Xms2gおよび-Xmx2g:ヒープメモリサイズ。1つ目は最小ヒープメモリ、2つ目は最大ヒープメモリ、より適切な値は2〜4g、GC時間は長くなります。
  2. -Xmn1gまたは(-XX:NewSize = 1gおよび-XX:MaxNewSize = 1g)または-XX:NewRatio = 1:新生代のサイズを設定します。JDKのデフォルトでは、新生代はヒープメモリサイズの1/3を占めます-XX:NewRatio=2これが1gセット、つまりです-XX:NewRatio=1必要に応じて設定できます。
  3. -XX:MetaspaceSize = 128mおよび-XX:MaxMetaspaceSize = 512mの場合、不滅の世代のJDK8は、マシンのほぼすべてのメモリを使用できます。過度のメモリ使用量が原因でサーバーが接続できなくなるのを防ぐために、次のことを行う必要があります。初期値を128M、最大値を512Mに設定します。
  4. -XX:SurvivorRatio:新生代の各生存領域のサイズ。デフォルトは8で、新生代の1 / 10、1 /(SurvivorRatio + 2)です。新生代に小さなポイントを設定したい人もいますが、避けてください。サイズが小さすぎるため、サバイバルエリアに一時的なオブジェクトを配置できず、古い世代に昇格したいと考えています。実際の状況を確認するのは、GCログからです。
  5. -Xss256k:ヒープの外側では、スレッドはスタックメモリを占有し、各スレッドはデフォルトで1Mです。メソッド呼び出し、ローカル変数、スカラー置換後のローカル変数などのスタックを格納します。メモリを節約し、より多くのスレッドを開くために小さなポイントを設定することを好む人もいます。ただし、とにかく、メモリが十分であれば、小さいサイズを設定する必要はありません。特にJSON解析などの再帰呼び出しがある場合は、大きいサイズを設定することを好む人もいます。
  6. -XX:MaxDirectMemorySize:オフヒープメモリ/ダイレクトメモリのサイズ。デフォルトは、ヒープメモリのサイズからサバイバー領域を引いたサイズです。
  7. -XX:ReservedCodeCacheSize:JITコンパイル後のバイナリコードのストレージ領域。いっぱいになると、コンパイルされません。デフォルトでは、マルチレイヤーコンパイルは240Mです。JMXでCodeCacheのサイズを確認できます。

GC設定

現在、より主流のGCはCMSとG1であり、一部の偉大な神々は8Gを境界として使用することを提案しています。(JDK 9のデフォルトはG1と言われています)。アプリケーションによって設定されるメモリは比較的小さいため、CMSコレクターが選択されます。以下のパラメーターもCMSコレクター用です。必要に応じて、待機後にG1コレクターのパラメーターを追加します。

CMS設定

  1. -XX:+ UseConcMarkSweepGC:CMSガベージコレクターを有効にする
  2. -XX:CMSInitiatingOccupancyFraction = 80および-XX:+ UseCMSInitiatingOccupancyOnly:2つのパラメーターを一緒に使用する必要があります。そうでない場合、最初のパラメーターの75は単なる参照値であり、JVMはGC時間を再計算します。
  3. -XX:MaxTenuringThreshold = 15:オブジェクトがサバイバーエリアのYoung GCを生き残り、古い世代に昇格した回数。デフォルトは15です。Young GCはアプリケーションの一時停止の最大の原因であり、新世代のGC後に存続するオブジェクトの数は一時停止時間に直接影響するため、Young GCの実行頻度と、アプリケーション内のほとんどの一時オブジェクトの最長のライフサイクルを知っている場合、使用できます短くすると、一時的なオブジェクトではない新世代の長期オブジェクトを古い世代にすばやく昇格させることができます。
  4. -XX:-DisableExplicitGC:System.gc()を使用してGCをアクティブに呼び出すことができます。ここで、JVM最適化の提案の中には、-XX:-DisableExplicitGCを設定し、System.gc()の手動呼び出しをオフにすることを説明する必要があります。これは、System.gc()がフルGCをトリガーし、頻繁なフルGCがパフォーマンスに深刻な影響を与えるためです。ただし、Nettyなどの多くのNIOフレームワークは、オフヒープメモリを使用します。フルGCがない場合、オフヒープメモリを再利用することはできません。System.gc()をアクティブに呼び出さない場合は、JVM自体がフルGCをトリガーするまで待つ必要があります。このとき、長い一時停止(STW)が発生し、マシンの負荷が増加する可能性があります。したがって、System.gc()を完全に禁止することはできず、フルGCの時間を短縮する必要があります。次に、-XX:+ExplicitGCInvokesConcurrentまたは-XX:+ExplicitGCInvokesConcurrentAndUnloadsClassesオプションを使用し、CMSコレクターを使用してフルGCをトリガーします。これらの2つのオプションは-XX:+UseConcMarkSweepGC一緒使用する必要があります
  5. -XX:+ ExplicitGCInvokesConcurrent:System.gc()を使用して、フルGCではなくCMSGCをトリガーします。デフォルトでは有効になっていません。このオプションは、-XX:+ UseConcMarkSweepGCオプションが使用されている場合にのみ有効にできます。
  6. -XX:+ ExplicitGCInvokesConcurrentAndUnloadsClasses:System.gc()を使用する場合、永続的な生成もCMSのスコープに含まれます。このオプションは、-XX:+ UseConcMarkSweepGCオプションが使用されている場合にのみオンにできます。
  7. -XX:+ ParallelRefProcEnabled:デフォルトはfalseです。WeakReferenceなどの参照オブジェクトは並行して処理されます。参照処理時間が長いログがGCログに表示されない限り、効果は明ら​​かではありません。
  8. -XX:+ ScavengeBeforeFullGC:フルGCが実行される前にヤングGCを1回実行します。
  9. -XX:+ UseGCOverheadLimit:GCの実行時間を制限します。GCに時間がかかりすぎる場合は、OOMをスローします。
  10. -XX:+ UseParallelGC:並列ガベージコレクターを設定します
  11. -XX:+ UseParallelOldGC:並列ガベージコレクターを使用するように古い世代を設定します
  12. -XX:-UseSerialGC:シリアルガベージコレクターをオフにします
  13. -XX:+ CMSParallelInitialMarkEnabledおよび-XX:+ CMSParallelRemarkEnabled:マークの一時停止を減らします
  14. -XX:+ CMSScavengeBeforeRemark:デフォルトはオフです。CMSがコメントする前に、マイナーGCを実行して新しい世代をクリアし、古い世代のオブジェクトから参照される新しい世代のオブジェクトの数を減らして、世界中のCMSを停止します。発言フェーズは短くなります。GCログのリマークフェーズに時間がかかりすぎる場合は、このアイテムをオンにして効果があるかどうかを確認できます。それ以外の場合は、オンにしないでください。無駄なYGCが増えます。
  15. -XX:CMSWaitDuration = 10000:ガベージコレクションの最大間隔を設定します。デフォルトは2000です。
  16. -XX:+ CMSClassUnloadingEnabled:フルGCを待たずに、CMSの永続世代で期限切れのクラスをクリーンアップします。JDK7はデフォルトで閉じられ、JDK8が開かれます。Groovyなどの動的言語スクリプトを実行して多数の一時クラスを生成するかどうかなど、状況によって異なります。これにより、CMSリマークの一時停止時間が長くなるため、新しいクラスが頻繁にロードされない場合、このパラメーターはまだ開かれていません。

GCログ

GCプロセスは、GCログを通じて最適化の基礎を提供できます。

  1. -XX:+ PrintGCDetails:gcログ印刷機能を有効にします
  2. -Xloggc:/path/to/gc.log:gcログの場所を指定します
  3. -XX:+ PrintHeapAtGC:GCの前後の詳細なスタック情報を出力します
  4. -XX:+ PrintGCDateStamps:タイムスタンプの代わりに読み取り可能な日付を出力します
  5. -XX:+ PrintGCApplicationStoppedTime:すべてのJVM一時停止時間を出力します。不明な一時停止が実際に見つかった場合は、一時的-XX:+PrintSafepointStatistics -XX: PrintSafepointStatisticsCount=1追加して理由を見つけてください。
  6. -XX:+ PrintGCApplicationConcurrentTime:2つの一時停止の間のJVMの通常の実行時間を出力し、-XX:+PrintGCApplicationStoppedTime一緒に使用すると効果が向上します。
  7. -XX:+ PrintTenuringDistribution:各マイナーGC後の新しい生存期間のしきい値を表示します
  8. -XX:+ UseGCLogFileRotationおよび-XX:NumberOfGCLogFiles = 10および-XX:GCLogFileSize = 10M:再起動後にGCログはクリアされますが、アプリケーションが長時間再起動しない場合、GCログが増加するため、これら3を追加します。パラメータ、ローリング方式でファイルに書き込まれるのはGCログですが、再起動すると名前がわかりにくくなる場合があります。
  9. -XX:PrintFLSStatistics = 1:各GCの前後のメモリの断片化に関する統計を出力します

その他のパラメータ設定

  1. -ea:アサーションを有効にします。これについては何も言うことはありません。有効にするか、無効にするかを選択できます。大きな違いはありません。それはそれ自身のシステムに従って完全に処理されます。
  2. -XX:+ UseThreadPriorities:スレッドの優先度を有効にします。これは主に、定期的なタスクの優先度を低くして、クライアントの作業への干渉を回避できるためです。私の現在の環境では、デフォルトで有効になっています。
  3. -XX:ThreadPriorityPolicy = 42:スレッドの優先度を下げることができます
  4. -XX:+ HeapDumpOnOutOfMemoryError:メモリオーバーフローが発生すると、ヒープダンプが実行されます
  5. -XX:HeapDumpPath = / path / to / java_pid.hprof:このパラメーターは、ヒープダンプを-XX:+HeapDumpOnOutOfMemoryError設定するときに出力ファイルと連動して機能します。
  6. -XX:ErrorFile = / path / to / hs_err_pid.log:致命的なエラーログの場所を指定します。通常、JVMで致命的なエラーが発生すると、hs_err_pid.logのようなファイルが出力されます。デフォルトは作業ディレクトリにあります(権限がない場合は、/ tmpに作成しようとします)が、自分で場所を指定することをお勧めします。これにより、収集と検索が容易になります。紛失を避けてください。
  7. -XX:StringTableSize = 1000003:文字列定数プールサイズを指定します。デフォルト値は60013です。Javaの常識が少しある人は、文字列は定数であり、作成後に変更できないことを知っておく必要があります。これらの定数が配置されている場所は、文字列定数プールと呼ばれます。システムに多くの文字列操作があり、これらの文字列値が比較的固定されている場合は、許可されていればプールサイズを適切に増やすことができます。
  8. -XX:+ AlwaysPreTouch:すべてのパラメータで定義されたすべてのメモリが起動時にストロークされます。このパラメータを使用すると、起動が遅くなる可能性がありますが、後のメモリ使用プロセスでは速くなります。これにより、メモリページの継続的な割り当てが保証され、新しい世代が昇格したときにメモリページが適用されたために、新しい世代によってGCが一時停止および拡張されることはありません。通常、メモリが32Gより大きい場合にのみ感じられます。
  9. -XX:-UseBiasedLocking:バイアスロックを無効にします(バイアスロックを無効にすると、多数のロックオブジェクトが作成され、高度に同時実行される環境(つまり、非マルチスレッドおよび高度に並行するアプリケーション)で特定のパフォーマンスが最適化されます)
  10. -XX:AutoBoxCacheMax = 20000:デジタルオブジェクトの自動ボクシングの範囲を拡大します。JDKのデフォルトは-128〜127 intおよびlongです。範囲を超えるとオブジェクトがすぐに作成されます。したがって、範囲を拡大するとパフォーマンスが向上しますが、パフォーマンスも向上します。テストが必要です。
  11. -XX:-OmitStackTraceInFastThrow:繰り返される例外のスタックを無視しないでください。これはJDKの最適化です。繰り返される多数のJDK例外は、StackTraceを出力しなくなります。ただし、システムが長時間再起動しないシステムであり、同じ場所でN個の複数の例外が実行されている場合、結果はJDKによって無視されます。特定のStackTraceが表示されないため、結果は無視されます。ログを表示するので、どのようにデバッグしますか?ログを閉じることをお勧めします。
  12. -XX:+ PerfDisableSharedMem:標準のメモリ使用量を有効にします。JVM制御は、標準メモリまたは共有メモリに分割されます。違いは、1つはJVMメモリにあり、もう1つは/ tmp / hsperfdata_ {userid} / {pid}ファイルを生成し、統計を保存し、mmapなどを介してメモリにマップすることです。プロセスはファイルアクセスコンテンツを渡すことができます。このパラメーターを使用すると、JVMがファイルに統計データを書き込むことを禁止できます。価格は、jpsおよびjstatコマンドが使用できなくなり、データはjmxを介してのみ取得できることです。ただし、トラブルシューティングでは、jpsやjstatなどの小さなツールは非常に使いやすく、jmxなどの重いツールよりもはるかに使いやすいため、独自に選択する必要があります。ここではGCポーズの一例です。
  13. -Djava.net.preferIPv4Stack = true:このパラメーターは、ネットワークの問題に属するパラメーターであり、必要に応じて設定できます。ipv6が有効になっている一部のマシンでは、を介してInetAddress.getLocalHost().getHostName()完全なマシン名を取得できますが、ipv4マシンでは、この方法で取得したマシン名が不完全な場合があり、このパラメーターを使用して完全なマシン名を取得できます。

偉大な神によって与えられた例

偉大なる神の例を以下に掲載しておりますので、参考にさせていただきますが、ご自身の環境で確認してからご利用いただくことをお勧めします。結局のところ、偉大な神の環境は自分の環境とは異なります。

パフォーマンス関連

-XX:-UseBiasedLocking -XX:-UseCounterDecay -XX:AutoBoxCacheMax = 20000
-XX:+ PerfDisableSharedMem(可選択)-XX:+ AlwaysPreTouch -Djava.security.egd = file:/ dev /./ urandom

メモリサイズ関連(JDK7)

-Xms4096m -Xmx4096m -Xmn2048m -XX:MaxDirectMemorySize = 4096m
-XX:PermSize = 128m -XX:MaxPermSize = 512m -XX:ReservedCodeCacheSize = 240M

jdk8を使用する場合は、-XX:PermSize = 128m -XX:MaxPermSize = 512mを-XX:MetaspaceSize = 128m -XX:MaxMetaspaceSize = 512mに置き換えます。前述のように、これら2つのパラメーターセットは安全性を確保するためのものです。追加。

CMSGC関連

-XX:+ UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction = 75
-XX:+ UseCMSInitiatingOccupancyOnly -XX:MaxTenuringThreshold = 6
-XX:+ ExplicitGCInvokesConcurrent -XX:+ ParallelRefProcEnabled

GCログ関連

-Xloggc:/dev/shm/app-gc.log -XX:+ PrintGCApplicationStoppedTime
-XX:+ PrintGCDateStamps -XX:+ PrintGCDetails

例外ログ関連

-XX:-OmitStackTraceInFastThrow -XX:ErrorFile = $ {LOGDIR} /hs_err_%p.log
-XX:+ HeapDumpOnOutOfMemoryError -XX:HeapDumpPath = $ {LOGDIR} /

JMX関連

-Dcom.sun.management.jmxremote.port = $ {JMX_PORT} -Dcom.sun.management.jmxremote
-Djava.rmi.server.hostname = 127.0.0.1 -Dcom.sun.management.jmxremote.authenticate = false
-Dcom。 sun.management.jmxremote.ssl = false

参考記事

  1. Javaパフォーマンス最適化ガイドバージョン1.8、およびVipshopの実際の戦闘
  2. Javaでのエスケープ分析とTLABおよびJavaオブジェクトの割り当て
  3. 4か月のバグ:JVM統計によりガベージコレクションが一時停止します

個人のホームページ:http//www.howardliu.cn

個人のブログ投稿:JVMパラメーターの最適化(基本記事)

CSDNホームページ:http://blog.csdn.net/liuxinghao

CSDNブログ投稿:JVMパラメーターの最適化(基本記事)

おすすめ

転載: blog.csdn.net/conansix/article/details/73963399