JVMの調整
Java仮想マシン(JVM)の調整は、主にJavaヒープおよび非ヒープ設定の調整とガベージコレクションの設定に重点を置いています。 自分に合った設定を見つけるには、お使いのシステムの負荷とハードウェアによって異なります。 ここで説明する設定は、JVMを調整するための開始点として使用できます。
サンプルのOracle JVM設定をJVMの設定に適合させることができます。 互換性のあるJVMについては、 互換性マトリックス を参照してください。
ヒープスペースと非ヒープスペースを設定する
JVMのメモリは、ヒープスペースと非ヒープスペースで構成されます。 ヒープには、若い世代のオブジェクト用のスペースと古い世代のオブジェクト用のスペースが含まれています。 静的コンテンツとジャストインタイム(JIT)コンパイル済みJavaコードは、非ヒープのネイティブスペースに格納されます。 構成例を次に示します。
メモリ設定の例
-Xms2560m -Xmx2560m
-XX:NewSize=1536m -XX:MaxNewSize=1536m
-XX:MetaspaceSize=768m -XX:MaxMetaspaceSize=768m
-XX:InitialCodeCacheSize=64m -XX:ReservedCodeCacheSize=96m
メモリ設定の説明
メモリ設定 | 説明 |
---|---|
-Xms2560m | ヒープの初期スペース。 |
-Xmx2560m | ヒープの最大スペース。 |
-XX:NewSize=1536m | 最初の新しいスペース。 通常、新しいサイズをヒープ全体の半分に設定すると、より小さな新しいサイズを使用するよりもパフォーマンスが向上します。 |
-XX:MaxNewSize=1536m | 最大の新しいスペース。 |
-XX:MetaspaceSize=768m | 静的コンテンツ用の初期スペース。 |
-XX:MaxMetaspaceSize=768m | 静的コンテンツ用の最大スペース。 |
-XX:InitialCodeCacheSize=64m | JITコンパイルされたコードの初期スペース。 コードキャッシュが小さすぎると(48m がデフォルト)、JITは高周波メソッドを最適化できないため、パフォーマンスが低下します。 |
-XX:ReservedCodeCacheSize=96m | JITコンパイルされたコードの最大スペース。 |
ヒープサイズの最小値 (-Xms
) と最大値 (-Xmx
) を同じ値に設定し、JVMがダイナミックに調整するのを防ぎます。
JVMヒープに32gを超える割り当てをしないでください。 ヒープサイズは、使用可能なCPUリソースの速度と量に見合ったものにする必要があります。
Survivor領域を設定する
(ヒープ内の)古い世代のスペースでは、ガベージコレクションが大量にあると、著しい速度低下を引き起こす可能性があります。 追加のオブジェクトを古い世代のスペースに昇格する前に Survivor領域 に長くとどまらせることで、この問題を回避します。 Survivor領域には、Edenのガベージコレクションで生き残った若い世代のオブジェクトが格納されています。 試してみる最初のSurvivor領域パラメーターは次のとおりです。
サバイバーの設定例
-XX:SurvivorRatio=16 -XX:TargetSurvivorRatio=50 -XX:MaxTenuringThreshold=15
サバイバーの設定の説明
サバイバー設定 | 説明 |
---|---|
-XX:SurvivorRatio=16 | Survivor領域を新しいスペースの1/16にします(最初の新しいスペースは 1536m )。 |
-XX:TargetSurvivorRatio=50 | 各Edenガベージコレクションの後にSurvivor領域の50%を使用するようにJVMに指示します。 |
-XX:MaxTenuringThreshold=15 | 旧世代のスペースに昇格する前に、最大15のガベージコレクション用にサバイバースペースにサバイバーを保持します。 |
ガベージコレクションを設定する
適切なガベージコレクター(GC)アルゴリズムを選択すると、Liferayインスタンスの応答性が向上します。
Java 8のガベージコレクション
新世代のパラレルスループットコレクター(ParNew)と旧世代のコンカレントマークスイープ(CMS)ローポーズコレクターを使用してチューニングを開始します。
GC設定の例
-XX:+UseParNewGC -XX:ParallelGCThreads=16
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled -XX:+CMSCompactWhenClearAllSoftRefs
-XX:CMSInitiatingOccupancyFraction=85 -XX:+CMSScavengeBeforeRemark
GC設定の説明
GC設定 | 説明 |
---|---|
-XX:+UseParNewGC | 新世代のパラレルコレクターを有効にします。 |
-XX:ParallelGCThreads=16 | パラレルガベージコレクションに16のスレッドを割り当てます。 使用可能なCPUスレッドに基づいてスレッド数を設定します。これは、Linuxでcat /proc/cpuinfo を実行することで取得できます。 スレッドは、旧世代のスペースのメモリを使用します。 |
-XX:+UseConcMarkSweepGC | 旧世代のコンカレントマークスイープGCアルゴリズムを有効にします。 |
-XX:+CMSParallelRemarkEnabled | プログラム実行中のリマークを有効にします。 |
-XX:+CMSCompactWhenClearAllSoftRefs | ClearAllSoftRefs 設定でCMSを使用する場合に、メモリブロックを互いに近づけます。 |
-XX:CMSInitiatingOccupancyFraction=85 | 旧世代のスペースでこのパーセントが占有されると、CMSを開始します。 |
-XX:+CMSScavengeBeforeRemark | CMSのオブジェクトを再マーキングする前に、Eden GCを実行します。 |
Garbage-First(G1)のような追加の「新しい」アルゴリズムがありますが、LiferayエンジニアリングのG1のテストでは、パフォーマンスが向上しないことが示されました。 アプリケーションのパフォーマンスは異なる可能性があるため、テストおよびチューニング計画にはG1を追加してください。
Java 11のガベージコレクション
CMSおよびParNewアルゴリズムはJava 11で廃止予定になっているため、Garbage-First(G1)アルゴリズムを使用してください。 デフォルトで有効になっています。 G1のデフォルト設定でテストを開始します。
大きなページの使用を検討する
大きなヒープサイズ(たとえば、4GB以上)を必要とするシステムでは、大きなページサイズを使用すると便利な場合があります。
マシンに大きなページを構成する
Linuxで大きなページ(別名「巨大なページ」)を構成する方法は次のとおりです。
-
ハードウェア仕様とアプリケーションプロファイルに基づいて、使用するページ数を決定します。 Linuxでは、次のコマンドを実行してページサイズを報告します。
cat /proc/meminfo | grep Hugepagesize
結果:
Hugepagesize = 2048 kB
-
有効にするページ数を設定します。 Linuxでは、
/etc/sysctl.conf
ファイルを編集し、vm.nr_hugepages
をページ数に設定します。 例:vm.nr_hugepages = 10
-
ページを有効にします。 Linuxでは、次のように実行します。
sysctl -p
-
マシンを再起動します。
JVMで大きなページを構成する
大きなページを使用するようにJVMを構成する方法は次のとおりです。
大きなページ設定の例
-XX:+UseLargePages -XX:LargePageSizeInBytes=256m
大きなページ設定の説明
大きなページ設定 | 説明 |
---|---|
-XX:+UseLargePages | 大きなページを有効にします。 |
-XX:LargePageSizeInBytes=256m | 大きなページの合計サイズ( cat /proc/meminfo からHugePages_Total * Hugepagesize を計算)に、JVMのすべてのメモリ使用量を含めることができることを確認してください。 |
ハードウェア仕様とアプリケーションプロファイルに基づいてページサイズを調整します。
まとめ
一般的なJVMオプションと構成例について理解したところで、テスト環境でそれらの実験を開始します。 ガベージコレクションの統計を監視して、環境に十分なメモリが割り当てられていることを確認します。 設定を調整して、パフォーマンスに対するガベージコレクションの影響を最小限に抑え、処理速度を最大化します。 適切なテストと調整を行うことで、Liferayインスタンス用にJVMを最適化できます。