33

デフォルトの JVM パラメータは、大規模なアプリケーションの実行には最適ではありません。実際のアプリケーションで調整した人からの洞察は役に立ちます。クライアント JVM がデフォルトで使用される 32 ビット Windows マシンでアプリケーションを実行しています。-server を追加し、NewRatio を 1:3 (より大きな若い世代) に変更しました。

他に試してみて役に立ったパラメータ/チューニングはありますか?

[更新] 私が話している特定の種類のアプリケーションは、めったにシャットダウンされず、少なくとも -Xmx1024m かかるサーバー アプリケーションです。また、アプリケーションはすでにプロファイリングされていると想定します。JVM のパフォーマンスのみに関する一般的なガイドラインを探しています。

4

7 に答える 7

36

序文

バックグラウンド

Javaショップに行ってきました。主なアプリケーションは Java である分散システムでのパフォーマンス テストの実行に専念するために丸 1 か月を費やしました。その中には、Sun 自身 (当時は Oracle) によって開発および販売された製品を暗示するものもあります。

私が学んだ教訓、JVM についての歴史、内部構造についての話、いくつかのパラメーターの説明、そして最後にいくつかのチューニングについて説明します。実際に適用できるように、それを要点に留めようとしています。

Java の世界では物事が急速に変化しているため、昨年私がすべてを行って以来、その一部はすでに時代遅れになっている可能性があります。(Java 10 はもう出ていますか?)

良い習慣

あなたがすべきこと:ベンチマーク、ベンチマーク、ベンチマーク!

パフォーマンスについて本当に知る必要がある場合は、ワークロードに固有の実際のベンチマークを実行する必要があります。代替手段はありません。

また、JVM を監視する必要があります。監視を有効にします。優れたアプリケーションは、通常、監視 Web ページや API を提供します。それ以外の場合は、一般的な Java ツール (JVisualVM、JMX、hprof、およびいくつかの JVM フラグ) があります。

通常、JVM を調整してもパフォーマンスは向上しないことに注意してください。それはむしろ「クラッシュするかクラッシュしないか、遷移点を見つける」ことです。その量のリソースをアプリケーションに与えると、その見返りとしてその量のパフォーマンスが一貫して期待できるということを知ることです。知識は力である。

パフォーマンスは主にアプリケーションによって決まります。より速くしたい場合は、より良いコードを書かなければなりません。

ほとんどの場合、信頼できる機密性の高いデフォルトで生活する

すべてのアプリケーションを最適化して調整する時間はありません。ほとんどの場合、適切なデフォルトをそのまま使用します。

新しいアプリケーションを構成するときに最初に行うことは、ドキュメントを読むことです。重要なアプリケーションのほとんどには、JVM 設定に関するアドバイスを含む、パフォーマンス チューニングのガイドが付属しています。

次に、アプリケーションを構成できます。JAVA_OPTS: -server -Xms???g -Xmx???g

  • -server: 完全な最適化を有効にします (このフラグは最近のほとんどの JVM で自動的に設定されます)
  • -Xms -Xmx: 最小ヒープと最大ヒープを設定します (両方の値は常に同じです。最適化はこれだけです)。

よくできました。JVM について知っておくべきすべての最適化パラメータについて理解できました。おめでとうございます! それは簡単でした:D

してはいけないこと:

インターネットで見つけたランダムな文字列をコピーしないでください。特に、次のような複数の行が含まれている場合は注意してください。

-server  -Xms1g -Xmx1g  -XX:PermSize=1g -XX:MaxPermSize=256m  -Xmn256m -Xss64k  -XX:SurvivorRatio=30  -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled  -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=10  -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark  -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Dsun.net.inetaddr.ttl=5  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof   -Dcom.sun.management.jmxremote.port=5616 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC

たとえば、Google の最初のページにあるこのことは、まったくひどいものです。競合する値を持つ引数が複数回指定されています。JVM のデフォルトを強制するだけのものもあります (最終的には、2 つ前の JVM バージョンのデフォルトになります)。いくつかは時代遅れであり、単に無視されています。そして最後に、少なくとも 1 つのパラメーターが無効であるため、単に存在するだけで起動時に JVM が一貫してクラッシュします。

実際のチューニング

メモリ サイズの選択方法:

アプリケーションからガイドを読んでください。何らかの兆候が見られるはずです。生産を監視し、後で調整します。精度が必要な場合は、いくつかのベンチマークを実行してください。

重要な注意: Java プロセスは、最大ヒープに 10%を加えた量を使用します。X% のオーバーヘッドはヒープ管理であり、ヒープ自体には含まれません。

通常、すべてのメモリは、起動時にプロセスによって事前に割り当てられます。常に最大ヒープを使用しているプロセスが表示される場合があります。それは単に真実ではありません。実際に何が使用されているかを確認するには、Java 監視ツールを使用する必要があります。

適切なサイズを見つける:

  • OutOfMemoryException でクラッシュする場合は、メモリが不足しています
  • OutOfMemoryException でクラッシュしない場合は、メモリが多すぎます
  • メモリが多すぎるが、ハードウェアがそれを取得したか、すでに支払い済みである場合、それは完璧な数であり、仕事は完了です!

JVM6 はブロンズ、JVM7 はゴールド、JVM8 はプラチナ...

JVM は常に改善されています。ガベージ コレクションは非常に複雑なものであり、多くの非常に賢い人々が取り組んでいます。過去 10 年間で大幅な改善が見られましたが、今後もその傾向が続くでしょう。

情報提供を目的としています。これらは、Oracle Java 7-8 (HotSpot) および OpenJDK 7-8 で少なくとも 4 つの利用可能なガベージ コレクターです。(他の JVM は、Android、IBM、組み込みなど、まったく異なる場合があります):

  • シリアルGC
  • パラレルGC
  • ConcurrentMarkSweepGC
  • G1GC
  • (およびバリアントと設定)

[Java 7 以降。Oracle と OpenJDK のコードは部分的に共有されています。GC は両方のプラットフォームで (ほとんど) 同じである必要があります。]

JVM >= 7 には多くの最適化があり、まともなデフォルトを選択します。プラットフォームによって少し異なります。それは複数のことをバランスさせます。たとえば、マルチコアの最適化を有効にするか、CPU に複数のコアがあるかどうかを決定します。あなたはそれをやらせるべきです。GC 設定を変更または強制しないでください。

コンピューターに決定を任せても問題ありません (それがコンピューターの目的です)。すべてのボックスで「一時停止時間を短縮するために常に 8 コアのアグレッシブ コレクション」を強制するよりも、JVM 設定を常に 95% 最適にする方がよいでしょう。

例外: アプリケーションにパフォーマンス ガイドと特定のチューニングが用意されている場合。提供された設定をそのままにしておくことはまったく問題ありません。

ヒント: 最新の改善点を利用するために新しい JVM に移行すると、多くの労力をかけずに十分なブーストが得られる場合があります。

特殊なケース: -XX:+UseCompressedOops

JVM には、内部で 32 ビットのインデックスを強制的に使用する特別な設定があります (読み取り: ポインターのようなもの)。これにより、4 294 967 295 オブジェクト * 8 バイト アドレス => 32 GB のメモリをアドレス指定できます。(REAL ポインターの 4GB アドレス空間と混同しないでください)。

これにより、全体的なメモリ消費量が削減され、すべてのキャッシュ レベルにプラスの影響を与える可能性があります。

実際の例: ElasticSearch のドキュメントでは、実行中の 32 GB 32 ビット ノードは、メモリに保持される実際のデータに関して 40 GB 64 ビット ノードと同等である可能性があると記載されています。

歴史に関する注意: フラグは、Java-7 より前の時代 (おそらく Java-6 より前) には不安定であることが知られていました。しばらくの間、新しいJVMで完全に機能しています。

Java HotSpot™ 仮想マシンのパフォーマンス強化

[...] Java SE 7 では、-Xmx が指定されていない場合、および -Xmx の値が 32 ギガバイト未満の場合、圧縮 oops の使用が 64 ビット JVM プロセスのデフォルトです。6u23 リリースより前の JDK 6 の場合、java コマンドで -XX:+UseCompressedOops フラグを使用して機能を有効にします。

参照: ここでも、JVM は手動チューニングよりも何年も先を行っています。それでも、それについて知ることは興味深いです =)

特殊なケース: -XX:+UseNUMA

Non-Uniform Memory Access (NUMA) は、マルチプロセッシングで使用されるコンピューターのメモリ設計です。メモリ アクセス時間は、プロセッサに対するメモリ位置によって異なります。出典:ウィキペディア

最新のシステムは、複数のレイヤーのメモリとキャッシュ (プライベートまたは共有) をコアと CPU にまたがって使用する、非常に複雑なメモリ アーキテクチャを備えています。

明らかに、現在のプロセッサの L2 キャッシュ内のデータにアクセスする方が、別のソケットからメモリ スティックにアクセスするよりもはるかに高速です。

現在販売されているすべてのマルチソケットシステムは設計上 NUMA ですが、コンシューマ システムはすべてそうではありません。numactl --showLinuxのコマンドを使用して、サーバーが NUMA をサポートしているかどうかを確認します。

NUMA 対応フラグは、基盤となるハードウェア トポロジのメモリ割り当てを最適化するよう JVM に指示します。

パフォーマンスが大幅に向上する可能性があります (つまり、2 桁: +XX%)。実際、「NOT-NUMA 10CPU 100GB」から「NUMA 40CPU 400GB」に切り替えると、フラグを知らなければパフォーマンスが[劇的に]低下する可能性があります。

注: NUMA を検出し、JVM http://openjdk.java.net/jeps/163でフラグを自動的に設定するための議論があります。

おまけ: 大きなファット ハードウェア (つまり NUMA) で実行するすべてのアプリケーションは、最適化する必要があります。これは、Java アプリケーションに固有のものではありません。

未来に向かって: -XX:+UseG1GC

ガベージ コレクションの最新の改善点は、G1 コレクター (読み取り: ガベージ ファースト)です。

これは、ハイ コア、ハイ メモリ システムを対象としています。絶対最小で 4 コア + 6 GB メモリ。これは、その 10 倍以上を使用するデータベースおよびメモリ集約型アプリケーションを対象としています。

短いバージョンですが、これらのサイズでは、従来の GC は一度に処理するには多すぎるデータに直面しており、一時停止が手に負えなくなっています。G1 はヒープを、アプリケーションの実行中に独立して並行して管理できる多くの小さなセクションに分割します。

最初のバージョンは 2013 年に利用可能になりました。現在は製品として十分に成熟していますが、すぐにデフォルトになることはありません。これは、大規模なアプリケーションで試してみる価値があります。

触れないでください: 世代サイズ (NewGen、PermGen...)

GC はメモリを複数のセクションに分割しました。(詳細には触れませんが、「Java GC Generations」をグーグルで検索できます。)

前回、10000ヒット/秒のアプリで世代フラグの20の異なる組み合わせを試すために1週間を費やしました。-1% から +1% の素晴らしいブーストを得ていました。

Java GC 世代は、論文を読んだり書いたりするのに興味深いトピックです。本当に最適化が必要な 1% の人々の中で、ごくわずかな利益のためにかなりの時間を費やすことができる 1% の一員でない限り、それらは調整するものではありません。

結論

これがあなたを助けることを願っています。JVM をお楽しみください。

Java は世界で最高の言語であり、最高のプラットフォームです! 愛を広めに行きましょう:D

于 2016-05-25T22:20:10.677 に答える
19

周りにはその情報がたくさんあります。

まず、JVM を調整する前にコードをプロファイリングします。

次に、JVM のドキュメントを注意深く読んでください。世の中には「都市伝説」がたくさんあります。たとえば、-server フラグは、JVM がしばらくの間常駐して実行されている場合にのみ役立ちます。-server は JIT/HotSpot を「起動」しますが、起動するには同じパスを通る多くのパスが必要です。一方、-server はセットアップ時間が長くなるため、JVM の初期実行が遅くなります。

周りには良い本やウェブサイトがいくつかあります。たとえば、http://www.javaperformancetuning.com/を参照してください。

于 2009-02-19T05:28:40.677 に答える
7

ここを見てください (または、ホットスポット チューニングについて Google 検索を行ってください) http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

VM を調整する前に、必ずアプリをプロファイリングする必要があります。NetBeans には、あらゆる種類のものを表示できる優れたプロファイラーが組み込まれています。

以前、アプリの GC が壊れていると誰かに言われたことがあります。コードを調べたところ、データベース クエリの結果がまったく閉じられていなかったため、大量のバイト配列が保持されていたことがわかりました。結果を閉じると、時間は 20 分以上とメモリ 1 GB から、約 2 分と非常に少量のメモリに短縮されました。彼らは JVM チューニング パラメータを削除することができ、状況は良好でした。

于 2009-02-19T05:54:27.120 に答える
1

CPU サンプリングとオブジェクト割り当ての監視を同時に有効にして、アプリケーションのプロファイリングを行うことをお勧めします。コードのチューニングに役立つ非常に異なる結果が得られることがわかります。また、組み込みの hprof プロファイラーを使用してみてください。同様に、非常に異なる結果が得られる可能性があります。

一般に、アプリケーションのプロファイリングは、JVM 引数よりもはるかに大きな違いをもたらします。

于 2009-02-19T22:48:04.563 に答える
1

32 ビット Windows マシン上の Java では、選択肢が限られています。私の経験では、次のパラメーター設定はアプリケーションのパフォーマンスに影響を与えます。

  1. メモリサイズ
  2. GC コレクターの選択
  3. GC コレクターに関連するパラメーター
于 2012-10-15T23:07:14.660 に答える
1

これに答える絶対的な最善の方法は、作成できる「本番」環境にできるだけ近いアプリケーションで制御されたテストを実行することです。-server の使用、妥当な開始ヒープ サイズ、および最近の JVM の比較的スマートな動作により、通常試行する大多数の設定と同等またはそれ以上の動作が得られる可能性は十分にあります。

この広範な一般化には、特定の例外が 1 つあります。Web コンテナーで実行している場合、永続世代の設定を増やしたい可能性が非常に高くなります。

于 2009-02-19T06:13:30.070 に答える
0

これは、アプリケーション、および JVM のベンダーとバージョンに大きく依存します。何をパフォーマンスの問題と考えるかを明確にする必要があります。コードの特定の重要なセクションに関心がありますか? アプリのプロファイリングはお済みですか? JVM がガベージ コレクションに多くの時間を費やしていませんか?

-verbose:gc JVM オプションから始めて、ガベージ コレクションがどのように機能しているかを監視します。多くの場合、 -Xmx を使用して最大ヒープ サイズを増やす最も簡単な修正方法です。-verbose:gc の出力を解釈できるようになれば、JVM 全体のチューニングについて知っておく必要のあるほとんどすべてのことがわかります。しかし、これだけを行っても、魔法のように調整が不十分なコードが高速になるわけではありません。JVM チューニング オプションのほとんどは、ガベージ コレクタのパフォーマンスやメモリ サイズを改善するように設計されています。

プロファイリングについては、 yourkit.comが好きです

于 2009-02-19T05:38:31.637 に答える