世代サイズに影響するパラメータはたくさんあります。図4-1「ヒープ・パラメータ」は、ヒープ内のコミットされた領域と仮想領域の違いを示しています。仮想マシンの初期化時に、ヒープの全体領域が確保されます。確保する領域のサイズは、-Xmx
オプションで指定できます。-Xms
パラメータの値が-Xmx
パラメータの値よりも小さい場合、確保されている領域の一部がただちに仮想マシン用にコミットされます。この図では、コミットされていない領域は「Virtual」と示されています。ヒープのそれぞれの部分(Tenured世代と若い世代)は、必要に応じて、仮想空間の制限までサイズを大きくすることができます。
パラメータのいくつかは、ヒープのある部分と他の部分の比率です。たとえば、パラメータNewRatio
は、Tenured世代の若い世代に対する相対サイズを示します。
次に示すヒープの拡大と縮小およびデフォルト・ヒープ・サイズに関する説明は、パラレル・コレクタには当てはまりません。(パラレル・コレクタにおけるヒープ・サイズの変更とデフォルト・ヒープ・サイズの詳細は、「世代のサイズ設定」の「パラレル・コレクタ・エルゴノミクス」を参照してください。)これに対して、ヒープの合計サイズと各世代のサイズを制御するパラメータは、パラレル・コレクタにも適用されます。
ガベージ・コレクションのパフォーマンスに影響する最も重要な要因は、使用可能なメモリーの総量です。コレクションは世代がいっぱいになると発生するので、スループットは使用可能なメモリーの量に反比例します。
デフォルトで、コレクションが発生するたびに、ライブ・オブジェクトに対する空き領域の割合が一定範囲内に保たれるように、仮想マシンによってヒープが拡大/縮小されます。この対象範囲は-XX:MinHeapFreeRatio=
<minimum>
パラメータと-XX:MaxHeapFreeRatio=
<maximum>
パラメータでパーセント値として設定され、合計サイズは下限値-Xms
<min>
と上限値-Xmx
<max>
によって制限されます。64ビットSolarisオペレーティング・システム(SPARC Platform Edition)用のデフォルト・パラメータを表4-1「64ビットSolarisオペレーティング・システム用のデフォルト・パラメータ」に示します。
表4-1 64ビットSolarisオペレーティング・システム用のデフォルト・パラメータ
パラメータ | デフォルト値 |
---|---|
|
|
|
|
|
|
|
|
これらのパラメータを使用した場合、世代の空き領域の割合が40%を下回ると、40%の空き領域を維持するように、世代の最大許容サイズを上回らない範囲で世代のサイズが拡大されます。同様に、空き領域の割合が70%を超えると、空き領域が70%以下になるように、世代の最小サイズを下回らない範囲で世代のサイズが縮小されます。
表4-1「64ビットSolarisオペレーティング・システム用のデフォルト・パラメータ」で示したように、デフォルトの最大ヒープ・サイズはJVMによって計算される値です。Java SEのパラレル・コレクタとサーバーJVMで使用されていた計算は、すべてのガベージ・コレクタで使用されるようになりました。最大ヒープ・サイズの上限の計算も含まれ、この値は32ビット・プラットフォームと64ビット・プラットフォームで異なります。「パラレル・コレクタ」の「デフォルト・ヒープ・サイズ」を参照してください。クライアントJVMにも同様の計算があり、サーバーJVMよりも最大ヒープ・サイズが小さくなります。
サーバー・アプリケーションのヒープ・サイズに関する一般的なガイドラインを次に示します。
一時停止が問題になっていなければ、できるだけ多くのメモリーを仮想マシンに割り当てます。多くの場合、デフォルトのサイズは小さすぎます。
-Xms
と-Xmx
を同じ値に設定すると、サイズについての最も重要な決断を仮想マシンが行う必要がなくなり、予測性が高まります。ただし、ユーザーの選択が不適切であった場合に、仮想マシンでは調整できません。
一般に、割当ては並列化できるので、プロセッサ数を増やすにつれて、メモリーも増やしてください。
使用可能なメモリー総量に次いで、ガベージ・コレクションのパフォーマンスに影響する重要な要因は、若い世代用のヒープの割合です。若い世代のサイズが大きいほど、マイナー・コレクションが発生しにくくなります。ただし、ヒープのサイズには制限があるので、若い世代を大きくすると、Tenured世代が小さくなり、メジャー・コレクションが発生しやすくなります。最適な選択は、アプリケーションによって割り当てられるオブジェクトの寿命分布に左右されます。
デフォルトで、若い世代のサイズはパラメータNewRatio
で制御します。たとえば、-XX:NewRatio=3
と設定すると、若い世代とTenured世代の比率が1:3になります。つまり、Eden領域とSurvivor領域の合計サイズが、合計ヒープ・サイズの1/4になります。
NewSize
パラメータとMaxNewSize
パラメータでは、若い世代のサイズの下限値と上限値を設定します。これらを同じ値に設定すると、若い世代のサイズが固定されます(-Xms
と-Xmx
を同じ値にすると、合計ヒープ・サイズが固定されるのと同じです)。これは、NewRatio
で許可されている整数倍よりもきめ細かく若い世代を調整できるので便利です。
パラメータSurvivorRatio
を使用すると、Survivor領域のサイズを調整できますが、これはパフォーマンスの点でそれほど重要にはなりません。たとえば、-XX:SurvivorRatio=6
と設定すると、Eden領域とSurvivor領域との比率が1:6になります。つまり、各Survivor領域のサイズはEden領域の1/6、すなわち若い世代の1/8になります(Survivor領域は2つあるので、1/7にはなりません)。
Survivor領域が小さすぎると、コピー方式コレクションがオーバーフローして、Tenured世代に直接送られてしまいます。Survivor領域が大きすぎると、使われない空間が無駄になります。仮想マシンは、ガベージ・コレクションのたびに、しきい値(Tenured世代に送るまでにオブジェクトをコピーできる回数)を選択します。このしきい値は、Survivor領域の使用率を半分以下に抑えるように選択されます。このしきい値と、新しい世代のオブジェクトの年齢を表示するには、コマンド行オプション-XX:+PrintTenuringDistribution
を使用します(一部のガベージ・コレクタではこのオプションを使用できません)。これは、アプリケーションの寿命分布を確認する場合にも役立ちます。
表4-2「Survivor領域のサイズ設定のデフォルト・パラメータ値」に、64ビットSolaris用のデフォルト値を示します。
表4-2 Survivor領域のサイズ設定のデフォルト・パラメータ値
パラメータ | サーバーJVMのデフォルト値 |
---|---|
|
|
|
|
|
無制限 |
|
|
若い世代の最大サイズは、ヒープ総量の最大サイズとNewRatio
パラメータの値から計算されます。MaxNewSize
パラメータのデフォルト値「無制限」は、コマンド行でMaxNewSize
に値を指定しないかぎり、計算値はMaxNewSize
で制限されないことを意味しています。
サーバー・アプリケーションの一般的なガイドラインを次に示します。
最初に、仮想マシンに割り当てる余裕のある最大ヒープ・サイズを決定します。次に、若い世代のサイズに対する独自のパフォーマンス・メトリックをグラフにして、最適な設定を求めます。
最大ヒープ・サイズは、マシンに搭載されたメモリー容量よりも必ず小さくして、過剰なページ・フォルトやスラッシングの発生を回避する必要があります。
合計ヒープ・サイズが固定されている場合、若い世代のサイズを増やすには、Tenured世代のサイズを減らす必要があります。アプリケーションによって一定期間使用されるすべてのライブ・データを保持するのに十分な大きさと、ある程度の余分な領域(10%から20%以上)をTenured世代に確保します。
前に説明したTenured世代の制約に従います。
十分な量のメモリーを若い世代に割り当てます。
割当ては並列化できるので、プロセッサ数を増やすにつれて、若い世代のサイズも大きくしてください。