Java-virtual-machine-tuning-gc

提供:Dev Guides
移動先:案内検索

Java仮想マシン-GCのチューニング

前の章では、さまざまな世代別Gcsについて学びました。 この章では、GCの調整方法について説明します。

ヒープサイズ

ヒープサイズは、Javaアプリケーションのパフォーマンスにおける重要な要素です。 小さすぎる場合は、頻繁にいっぱいになるため、GCによって頻繁に収集する必要があります。 一方、ヒープのサイズを増やすだけでは、収集の頻度を減らす必要がありますが、一時停止の長さが長くなります。

さらに、ヒープサイズを増やすと、基盤となるOSに重大なペナルティが生じます。 OSは、ページングを使用して、アプリケーションプログラムに実際に利用可能なメモリよりもはるかに多くのメモリを認識させます。 OSは、ディスク上の一部のスワップスペースを使用してこれを管理し、プログラムの非アクティブ部分をそこにコピーします。 これらの部分が必要になると、OSはそれらをディスクからメモリにコピーします。

マシンに8Gのメモリがあり、JVMが16Gの仮想メモリを認識している場合、JVMはシステムで実際に8Gしか使用できないことを知りません。 OSに16Gを要求するだけで、そのメモリを取得すると、それを使用し続けます。 OSは大量のデータを入出力する必要があり、これはシステムのパフォーマンスを大幅に低下させます。

そして、そのような仮想メモリのフルGC中に発生する一時停止が発生します。 GCは、収集と圧縮のためにヒープ全体に作用するため、仮想メモリがディスクからスワップアウトされるまでかなり待たなければなりません。 コンカレントコレクターの場合、バックグラウンドスレッドは、スワップスペースからメモリにデータがコピーされるのをかなり待たなければなりません。

そのため、最適なヒープサイズをどのように決定すべきかという問題が生じます。 最初のルールは、実際に存在する以上のメモリをOSに要求しないことです。 これにより、頻繁なスワッピングの問題を完全に防ぐことができます。 マシンに複数のJVMがインストールされて実行されている場合、それらすべてを組み合わせた合計メモリ要求は、システムに存在する実際のRAMよりも少なくなります。

あなたは2つのフラグを使用して、JVMによるメモリ要求のサイズを制御することができます-

  • -XmsN -要求された初期メモリを制御します。
  • -XmxN -要求できる最大メモリを制御します。

これら両方のフラグのデフォルト値は、基盤となるOSによって異なります。 たとえば、MacOS上で実行されている64b JVMの場合、-XmsN = 64Mおよび-XmxN =最小1Gまたは合計物理メモリの1/4です。

JVMは2つの値を自動的に調整できることに注意してください。 たとえば、GCが多すぎることに気付いた場合、-XmxN未満であり、目的のパフォーマンス目標が満たされている限り、メモリサイズを増やし続けます。

アプリケーションに必要なメモリ量が正確にわかっている場合は、-XmsN = -XmxNを設定できます。 この場合、JVMはヒープの「最適な」値を把握する必要がないため、GCプロセスの効率が少し向上します。

世代サイズ

YGに割り当てるヒープの量と、OGに割り当てるヒープの量を決定できます。 これらの値は両方とも、次のようにアプリケーションのパフォーマンスに影響します。

YGのサイズが非常に大きい場合、収集される頻度は少なくなります。 これにより、OGに昇格されるオブジェクトの数が少なくなります。 一方、OGのサイズを大きくしすぎると、OGの収集と圧縮に時間がかかりすぎ、STWの一時停止が長くなります。 したがって、ユーザーはこれら2つの値のバランスを見つける必要があります。

以下は、これらの値を設定するために使用できるフラグです-

  • * -XX:NewRatio = N:* YGとOGの比率(デフォルト値= 2)
  • * -XX:NewSize = N:* YGの初期サイズ
  • * -XX:MaxNewSize = N:* YGの最大サイズ
  • * -XmnN:*このフラグを使用して、NewSizeとMaxNewSizeを同じ値に設定します

YGの初期サイズは、指定された式によるNewRatioの値によって決定されます-

(total heap size)/(newRatio + 1)

newRatioの初期値は2であるため、上記の式はYGの初期値を合計ヒープサイズの1/3に設定します。 NewSizeフラグを使用してYGのサイズを明示的に指定することにより、いつでもこの値をオーバーライドできます。 このフラグにはデフォルト値はありません。明示的に設定されていない場合、YGのサイズは上記の式を使用して計算され続けます。

パーマージェンとメタスペース

パーマゲンとメタスペースは、JVMがクラスのメタデータを保持するヒープ領域です。 Java 7ではスペースは「パーマジェン」と呼ばれ、Java 8では「メタスペース」と呼ばれます。 この情報は、コンパイラとランタイムによって使用されます。

次のフラグを使用して、パーマジェンのサイズを制御できます: -XX:PermSize = N および -XX:MaxPermSize = N 。 メタスペースのサイズは、-XX:Metaspace- Size = N *および *-XX:MaxMetaspaceSize = N を使用して制御できます。

フラグ値が設定されていない場合のパーマゲンとメタスペースの管理方法にはいくつかの違いがあります。 デフォルトでは、両方にデフォルトの初期サイズがあります。 ただし、メタスペースは必要なだけヒープを占有できますが、パーマジェンはデフォルトの初期値を超えて占有することはできません。 たとえば、64b JVMには最大永久磁石サイズとして82Mのヒープスペースがあります。

メタスペースは、指定しない限り無制限のメモリを占有できるため、メモリ不足エラーが発生する可能性があることに注意してください。 これらの領域のサイズが変更されるたびに、フルGCが実行されます。 したがって、起動中にロードされるクラスが多数ある場合、メタスペースはサイズ変更を続けることができ、その結果毎回フルGCになります。 したがって、初期メタスペースのサイズが小さすぎる場合、大規模なアプリケーションの起動には多くの時間がかかります。 起動時間を短縮するため、初期サイズを増やすことをお勧めします。

パーマゲンとメタスペースはクラスのメタデータを保持しますが、永続的ではなく、オブジェクトの場合と同様に、スペースはGCによって回収されます。 これは通常、サーバーアプリケーションの場合です。 サーバーに新しい展開を行うたびに、新しいクラスローダーにはスペースが必要になるため、古いメタデータをクリーンアップする必要があります。 このスペースはGCによって解放されます。