JVM パフォーマンスの調整と実際の戦闘の進行状況を 20 分で理解できるようにします

ZGC

出生理由

Java エコシステムは非常に強力ですが、それだけでは十分ではありません.一部のシナリオではまだ不利な状況にあり、ZGC の出現により、Java 言語が他の言語の特定の領域で市場を掌握できるようになる可能性があります. 例えば

  • Google が支配する Android 携帯電話システムがフリーズします。
  • 証券取引所市場には非常に高いリアルタイム要件があり、現在は主に C++ が支配しています。
  • HBase などのビッグ データ クラスターのパフォーマンス。

特性

  • ZGC (The Z Garbage Collector) は、JDK11 向けの低遅延ガベージ コレクターを開始しました。STW は一時停止時間が 1 ミリ秒未満であることを意味し、ヒープのサイズが増加しても増加しません。
  • 主な原則を実現する: 完全な同時処理 (GC ROOTS のトラバースが一時停止される場合のみ)

  • JDK16 以降のバージョンでは、16TB レベルのヒープがサポートされています。
  • 主な原則を実現する: リージョン パーティション管理、染色ポインターのアドレス指定

  • アプリケーションのスループットが最大 15% 低下します。
  • 実装の主な原則:ライフサイクルの短いオブジェクトの割り当て率が高い場合、多数のオブジェクトがマークされて収集されず、大量の浮遊ガベージが生成され、スループットに影響し、ヒープ内の転送可能なオブジェクトのスペースがますます小さくなります。

  • 将来の新しい GC 機能の基礎を築きます。
  • 主な原則を理解してください: カラーリング ポインターの未使用の予約済み 18 ビット。

メモリ レイアウト

ZGC はヒープ スペース ページング モデルのメカニズムを採用しており、ヒープ スペース ページング モデルも、Linux Kernel2.6 で導入された 4KB などの標準的なヒュージ ページ (huge page) の処理方法と非常に一致しています。本質はG1と同じで、世代という概念がなく、ZGCもRegionに基づくヒープメモリレイアウトを採用している.違いは、ZGCのRegionが動的であることである:動的に作成および破棄され、動的な容量サイズである. ZGC は 3 つのリージョンに分かれています。

  • 小領域 (小ページ): 容量は 2MB に固定され、256KB 未満のオブジェクトが格納されます。
  • 中規模リージョン (中ページ): 容量は 32MB 固定で、256KB より大きく 4MB より小さいオブジェクトが格納されます。
  • ラージ リージョン (ラージ ページ): 容量は 2*N MB で、動的に変更できます. 各ラージ リージョンには 1 つのラージ オブジェクトのみが格納され、再割り当てされません (つまり、後述するオブジェクトのコピー)。 、大きなオブジェクトのコピーはコストがかかるためです。

ポインターの色付けテクニック (Color Pointers)

  • ZGC は 64 ビット システム、つまり 64 ビット ポインターのみをサポートします。
  • JDK11 の ZGC の ZGC は、下位 42 ビット、つまり 2 の 42 乗を分析して、使用中のヒープ領域、つまり管理可能なメモリを示します。これは、JDK の以降のバージョンで変更されます。
  • ZGC は、複数の高レベル ビットを使用して、GC 関連の高速同時マーキング、転送、ガベージ コレクションの再配置などを行います。
  • 将来の GC の新機能のために予約されている拡張ポイント

C プログラムのマッピング.c ZGC の 64 ビット仮想アドレス空間のポインター カラーリング テクノロジーの表示を見てください。

コンパイルして実行すると、3 つのアドレスは同じです。つまり、同じ実アドレスが 3 つの仮想アドレスにマッピングされます。

全体的なプロセス

概要

大きく分けて2段階

  • マークフェーズ(マークゴミ)
  • 転送フェーズ (オブジェクトのコピーまたは移動)

ゴミマーク

ガベージ マーキング アルゴリズムは到達可能性分析アルゴリズムを採用

  • 再マッピング
  • GC の前のすべてのメモリが再マップされるか、マーキング後にまだ再マップされている場合はガベージです。

  • M0、例として 2 つの GC が発生し、M0 は 1 つの GC です。
  • 前の GC のマーキング フェーズでマークされたが、最後の GC で転送されなかったアクティブなオブジェクト。

  • M1、例として 2 つの GC が発生し、M0 は 2 つの GC です。
  • このガベージ コレクションで識別されたライブ オブジェクト。

マーク フェーズ、オブジェクトの割り当て (リマップ)

  • 初期タグ(タグルート)
  • 同時採点(残印)
  • 再ラベル付け (欠落したラベルの解決)

マーキングが終了すると、Remapped オブジェクトはガベージ オブジェクトになります。次のマークは M1 を使用してアクティブであることを示します。

ZGC 転送

  • 同じページであればマークアップに相当します。
  • それが別のページであれば、コピー アルゴリズムと同等です。

JVM チューニングの概要

バックグラウンド

  • 本番環境の問題
  • 本番環境の問題。
  • 本番環境でメモリ オーバーフローが発生した場合はどうすればよいですか?
  • 本番環境でサーバーに割り当てるメモリの量はどれくらいですか?
  • ガベージ コレクタのパフォーマンスを調整するにはどうすればよいですか?
  • 本番環境で高い CPU 負荷に対処するにはどうすればよいですか?
  • 本番環境でアプリケーションに割り当てられるスレッドの数は?
  • ログを追加せずに、特定のコード行がリクエストによって実行されたかどうかを判断する方法は?
  • ログを追加せずに、メソッドの入力と戻り値をリアルタイムで確認する方法は?

  • チューニングする理由
  • OOMを防ぐ
  • OOMを解決する
  • Full GC の頻度を減らす

  • チューニングシーン
  • Full GC の回数が多い。
  • GC の一時停止時間が長すぎます (1 秒以上)。
  • アプリケーションに OutOfMemory などのメモリ例外があります。
  • システムのスループットと応答性能が高くない、または低下している

  • さまざまな段階での考慮事項
  • ライブに行く前に
  • プロジェクト運用フェーズ
  • OOMがオンラインに登場

チューニングの概要

  • モニタリングの基礎
  • 実行ログ
  • 例外スタック
  • GC ログ
  • スレッドのスナップショット
  • ヒープダンプのスナップショット

  • チューニングの一般的な方向性
  • 賢明にコードを書く
  • ハードウェア リソースの完全かつ合理的な使用
  • 妥当な JVM チューニング

チューニングターゲット

JVM チューニングの目標は、より小さいメモリ フットプリントを使用して、より高いスループットまたはより低いレイテンシを取得することです. ここから、次の 3 つの重要な指標があることもわかります。

  • メモリ使用量: プログラムの通常の動作に必要なメモリ サイズ。
  • 待ち時間: ガベージ コレクションによるプログラムの一時停止時間。
  • スループット: ユーザー プログラムとガベージ コレクションに費やされた合計時間に対するユーザー プログラムの実行時間の比率。

上記のことから、分散 CAP 理論のように、これら 3 つを完全に組み合わせることができないこともわかります.Java プログラムでは、メモリ使用量の削減、レイテンシの削減、スループットの向上を同時に実現することは不可能です。他のインジケーターのパフォーマンスを犠牲にして、両方を持つことはできません。プログラムの目的が異なり、チューニングの方向性も異なるため、実際のシナリオを組み合わせ、最適化の目標を明確にし、パフォーマンスのボトルネックを見つけて、ターゲットを絞ってボトルネックを最適化する必要があります。

チューニングの原則

  • 90%、つまり、ほとんどの Java アプリケーションは JVM の最適化を必要としません。
  • GC の問題の原因のほとんどは、コード レベル (コード レベル) の問題によって引き起こされます。
  • オンラインにする前に、マシンの JVM パラメータを最適に設定することを検討する必要があります。
  • 作成されるオブジェクトの数を減らし、グローバル変数と大きなオブジェクト (コード レベル) の使用を減らします。
  • アーキテクチャのチューニングとコードのチューニングを優先し、JVM の最適化は最後の手段です。
  • コードを最適化するために GC 状況を分析することは、JVM パラメーターを最適化するよりも優れています。

チューニング手順

  • ステップ 1: パフォーマンスの監視
  • GCが頻繁
  • CPU 負荷が高すぎる (top -hP プロセス番号、top -d 2 -c など)。
  • OOM
  • メモリーリーク
  • デッドロック
  • プログラムの応答時間が長い

  • ステップ 2: パフォーマンス分析
  • GC ログを印刷し、GCviewer または gceasy を介して例外情報を分析します
  • コマンド ライン ツール、jstack、jmap、jinfo などの柔軟な使用。
  • ヒープ ファイルをダンプし、メモリ分析ツールを使用してファイルを分析します。
  • Ali Arthas、jconsole、JVisualVM を使用して JVM のステータスをリアルタイムで表示する
  • jstack ビューのスタック情報

  • ステップ 3: パフォーマンスの調整
  • 事業背景に応じてメモリを適切に増やし、ガベージ コレクタを選択する
  • コードの最適化、メモリ使用量の制御
  • マシンを追加してノードの圧力を分散する
  • スレッド プール内のスレッド数を適切に設定する
  • ミドルウェアを使用して、キャッシング、メッセージ キューなど、プログラムの効率を向上させます。

性能評価・試験指標

  • 一時停止時間 (または応答時間)
  • リクエストを送信してから、そのリクエストに対するレスポンスを返すまでにかかった時間で、通常は平均レスポンス タイムに注目します。
  • データベース内のレコード (インデックス付き) をクエリするには、10 ミリ秒以上かかります。
  • 機械ディスクは、一度アドレス指定され、配置されます。4ミリ秒
  • メカニカル ディスクから 1M データをシーケンシャルに読み取ります。2ミリ秒
  • SSD ディスクから 1M データをシーケンシャルに読み取ります。0.3ミリ秒
  • メモリから 1M データを読み取ります。10マイクロ秒
  • Java プログラムのネイティブ メソッド呼び出し。数マイクロ秒
  • ネットワークは 2Kb のデータを転送します。1マイクロ

  • スループット
  • 単位時間あたりに完了した作業 (リクエスト) の量の尺度
  • GC: 合計実行時間に対するユーザー コードを実行するイベントの割合 (合計実行時間: プログラム実行時間 + メモリ回復時間)
  • スループットは 1-1/(1+n)、ここで -XX::GCTimeRatio=n

  • メモリ使用量
  • Javaヒープ領域が占有するメモリサイズ

  • 相互関係
  • 高速道路の交通状況を例にとる
  • スループット:高速道路の料金所を毎日通過する車両のデータ
  • 同時台数:高速道路を走行している車両の台数
  • 応答時間: 車速

JVM 監視および診断コマンドライン ツール

モニタリングなし、チューニングなし!コマンド ラインは、jdk の bin ディレクトリをインストールします。これらのツールは、ターゲット JVM のさまざまな側面とレベルの情報を取得するために使用され、開発者が Java アプリケーションの難病を解決するのに役立ちます。

  • 実行中の Java プロセスを表示: jps
  • jps (Java プロセス ステータス): 指定したシステム内のすべての HotSpot 仮想マシン プロセスを表示し (仮想マシン プロセス情報を表示)、実行中の仮想マシン プロセスのクエリに使用できます。
  • ローカル仮想マシン プロセスの場合、プロセスのローカル仮想マシン ID はオペレーティング システムのプロセス ID と一致し、一意です。
  • 基本的な使用構文は次のとおりです: jps [オプション] [ホストID]

  • JVM 統計の表示: jstat
  • jstat (JVM Statistics Monitoring Tool): 仮想マシンのさまざまな実行ステータス情報を監視するためのコマンドライン ツール。ローカルまたはリモートの仮想マシン プロセスで、クラスのロード、メモリ、ガベージ コレクション、JIT コンパイルなどの実行中のデータを表示できます。GUI グラフィカル インターフェイスを持たず、プレーン テキスト コンソール環境のみを提供するサーバーでは、実行時に仮想マシンのパフォーマンスの問題を特定するための最初の選択肢になります。一般に、ガベージ コレクションの問題やメモリ リークを検出するために使用されます。(一般的な本番環境にはGUIツールはなく、シンプルでよく使われています)
  • 基本的な使用構文は次のとおりです。 jstat - [-t] [-h] [ []]、たとえば jstat -gc process id 1000 10
  • jstat を使用して、メモリ リークがあるかどうかを判断することもできます。
  • 実行時間の長い Java プログラムでは、jstat コマンドを実行して複数行のパフォーマンス データを継続的に取得し、これらのデータ行で OU 列 (つまり、占有されている古い時代のメモリ) の最小値を取得できます。
  • 次に、上記の操作を長期間の間隔で繰り返し、複数の OU グループの最小値を取得します。これらの値が上昇傾向にある場合は、Javaプログラムの古い世代のメモリ使用量が増加していることを意味し、リサイクルできないオブジェクトが増加していることを意味するため、メモリ リークの可能性が高くなります。

  • JVM構成パラメータをリアルタイムで表示および変更: jinfo
  • jinfo (Java の構成情報): 仮想マシンの構成パラメーター情報を表示し、仮想マシンの構成パラメーターの調整にも使用できます。
  • 基本的な使用構文は次のとおりです。 jinfo [options] pid (jinfo -sysprops プロセス ID など)

  • メモリ イメージ ファイルとメモリ使用量のエクスポート: jmap
  • ダンプ ファイル (ヒープ ダンプ スナップショット ファイル、バイナリ ファイル) を取得します。Java ヒープの各領域の使用状況、ヒープ内のオブジェクトの統計、クラスなど、対象の Java プロセスのメモリ関連情報も取得できます。ロード情報など
  • 基本的な使用構文は次のとおりです。
  • jmap [オプション]
  • jmap [オプション] <実行可能ファイル
  • jmap [オプション] [server_id@]

  • 使用 1: メモリ イメージ ファイルのエクスポート
  • 手動の方法
  • jmap -dump:format=b,file=<ファイル名.hprof>
  • jmap -dump:live,format=b,file=<ファイル名.hprof>

  • 使用 2: ヒープ メモリ関連情報の表示
  • jmap -ヒープ プロセス ID
  • jmap -histo プロセス ID

  • 用途 3: その他の機能
  • jmap -permstat プロセス ID
  • システムの ClassLoader 情報を表示する
  • jmap -ファイナライザー情報
  • ファイナライザ キューに蓄積されたオブジェクトを表示する

  • JDK には、ヒープ分析ツール jhat が付属しています。
  • jhat (JVM Heap Analysis Tool): Sun JDK が提供する jhat コマンドを jmap コマンドと組み合わせて使用​​し、jmap によって生成されたヒープ ダンプ ファイル (ヒープ ダンプ スナップショット) を分析します。jhat には小さな HTTP/HTML サーバーが組み込まれており、ダンプ ファイルの分析結果を生成した後、ユーザーは分析結果をブラウザーで表示できます (仮想マシンのダンプ スナップショット情報を分析します)。
  • jhat コマンドを使用すると、http サービスが開始され、ポートは 7000、つまり http://localhost:7000/ になり、ブラウザーで分析できます。
  • 注: jhat コマンドは JDK9 および JDK10 で削除されており、代わりに VisualVM を使用することが公式に推奨されています。
  • 基本的な適用文法: jhat

  • JVM でスレッドのスナップショットを出力: jstack
  • jstack (JVM スタック トレース): 現時点での仮想マシンの指定されたプロセスのスレッド スナップショット (仮想マシン スタック トレース) を生成するために使用されます。スレッド スナップショットは、現在の仮想マシンで指定されたプロセスの各スレッドによって実行されているメソッド スタックのコレクションです。
  • スレッド スナップショットを生成する機能: スレッド間のデッドロック、無限ループ、外部リソースの要求によって引き起こされる長い待機など、スレッドの長い一時停止の理由を特定するために使用できます。これらは、長いスレッド一時停止の一般的な原因です。スレッドが一時停止すると、jstack を使用して、各スレッド呼び出しのスタック ステータスを表示できます。
  • 基本的な構文: jstack [オプション] pid

  • 多機能コマンドライン: jcmd
  • JDK 1.7 以降、新しいコマンドライン ツール jcmd が追加されました。これは、jstat を除く以前のすべてのコマンドの機能を実現するために使用できる多機能ツールです。例: ヒープのエクスポート、メモリ使用量、Java プロセスの表示、スレッド情報のエクスポート、GC の実行、JVM ランタイムなどに使用します。
  • jcmd -l : すべての JVM プロセスを一覧表示します
  • jcmd pid help : 指定されたプロセスについて、サポートされているすべての特定のコマンドを一覧表示します
  • jcmd pid 特定コマンド: 指定プロセスの命令コマンドのデータを表示

  • リモートホスト情報収集:jstatd
  • これまでの手順では、ネイティブ Java アプリケーションの監視のみが行われました。これらのツールの中には、リモート コンピューターの監視もサポートする監視ツール (jps、jstat など) があります。リモート監視を有効にするには、jstatd ツールを使用する必要があります。コマンド jstatd は RMI サーバー プログラムで、プロキシ サーバーとして機能し、ローカル コンピューターとリモート監視ツール間の通信を確立します。jstatd サーバーは、Java アプリケーション情報をローカル マシンからリモート マシンに渡します。

JVM 監視および診断ツール GUI

Arthas は JVM の監視および診断ツールの GUI でもあることは以前に説明しましたが、この記事ではまず影を落とし、次に焦点を当てます。

  • JDK に付属のツール
  • jconsole: JDK に付属するビジュアル監視ツール。Java アプリケーションの実行中のプロファイルを表示し、ヒープ情報、永続領域 (またはメタスペース) の使用状況、クラスのロードなどを監視します。
  • Java5 以降、JDK に付属する Java 監視および管理コンソール。これは、JVM のメモリ、スレッド、およびクラスを監視するための JMX (Java 管理拡張機能) に基づく GUI パフォーマンス監視ツールです。

  • Visual VM: Visual VM は、Java 仮想マシンで実行されている Java テクノロジ ベースのアプリケーションの詳細を表示するための視覚的なインターフェイスを提供するツールです。
  • VisualVM は、トラブルシューティングとパフォーマンス監視のための強力なオールインワン ビジュアル ツールです。
  • 複数の JDK コマンドライン ツールを統合し、VisualVM を使用して、仮想マシン プロセスとプロセス構成および環境情報 (jps、jinfo) を表示し、アプリケーション CPU、GC、ヒープ、メソッド領域、およびスレッド情報 (jstat、jstack) を監視するために使用できます。など、JConsole 用。
  • JDK 6 Update 7 以降、Visual VM は JDK の一部としてリリースされます (VisualVM は JDK/bin ディレクトリにあります)。さらに、Visual VM はスタンドアロン ソフトウェアとしてインストールすることもできます。

  • JMC: Java Mission Control、ビルトイン Java Flight Recorder。非常に低いパフォーマンス オーバーヘッドで Java 仮想マシンのパフォーマンス データを収集する機能。

  • サードパーティのツール
  • MAT: MAT (Memory Analyzer Tool) は Eclipse ベースのメモリ分析ツールで、高速で機能豊富な Java ヒープ分析ツールであり、メモリ リークを見つけてメモリ消費を削減するのに役立ちます。
  • MAT は普遍的なツールではなく、すべてのタイプのヒープ ストレージ ファイルを処理できるわけではありません。ただし、Sun、HP、および SAP で使用される HPROF バイナリ ヒープ ストレージ ファイルや、IBM の PHD ヒープ ストレージ ファイルなど、主流のメーカーと形式はすべて適切に解析できます。
  • 最も魅力的なのは、問題の特定と分析に便利な、開発者向けのメモリ リーク レポートをすばやく生成できることです。MAT は非常に強力な機能を備えていますが、メモリの分析はワンクリックで完了するほど簡単ではなく、MAT が表示する情報から経験と勘によって発見する必要があるメモリの問題は依然として多くあります。

  • JProfiler: 有料の商用ソフトウェア。パワフル。
  • フレーム グラフ (フレーム グラフ), 極端なパフォーマンス シナリオを追求する場合, プログラムの実行中に CPU が何をしているかを理解することが非常に重要です. フレーム グラフは、実行中の CPU の時間割り当てを表示するための非常に直感的なツールです.プログラムのライフ サイクル全体と、find を呼び出す際の CPU 消費のボトルネック。

さらに、JVM ランタイム パラメータと GC ログの分析については、特別なドキュメントが個別に追加されます。

おすすめ

転載: blog.csdn.net/a448335587/article/details/129504039