Scavenge GCのチューニング
ここまでの説明によって、JVMが出力するガベージ・コレクション・ログの内容をより掘り下げて理解できるはずです。例えばHP JVMの場合、前回紹介した拡張オプション「-Xverbosegc」とログ加工用スクリプト「processVerboseGC.awk」を使えば、以下のような出力が得られます。
eden: 1834928->0/3670016
このログは、以下のように解釈します。
- GC前、Eden領域の消費サイズは「1834928」バイトであった
- GC後、Eden領域の消費サイズは「0」バイトであった(つまり全オブジェクトが移動もしくは破棄された)
- GC後、Eden領域のサイズは「3670016」バイトであった
From領域およびTo領域についても、これと同様の方法でログの解釈が可能です。
survivor: 120576->0/262144
「survivor」とは、From領域とTo領域両方を指します。ここでもし、上記ログのようにGC後のFrom/To領域の消費サイズが「0」となった場合は注意が必要です。これはすなわち、オブジェクトがFrom領域とTo領域の間を行き来せず、すぐにOLD領域に移動してしまっていることを表します。このような状況では、OLD領域は短命なオブジェクトですぐに埋まり、Full GCが頻発してしまいます。これはオーバーフローと呼ばれ、MaxTenuringThreshold値の低い状態で一連のGCが発生している状況を見つけることで検出できます。
NEW領域のサイズ調節
MaxTenuringThreshholdの値は、ガベージ・コレクションが進行するに従い調整されるため、プログラム実行中は常に変化する可能性があります。NEW領域が小さすぎ、オブジェクトを短期間しか保持できない状況では、MaxTenuringThreshholdの値が低下しオブジェクトはNEW領域からOLD領域へ過度に移動しやすくなります。これは避けるべき状況です。そこで、Full GCの回数を減らすことを目的として、以下のようなチューニングを実施します。
NEW領域を拡大するには、-Xmnオプションを用いて同領域のサイズを指定します。これにより、NEW領域内の全ての領域(Eden、From、To)が拡張されます。同オプションは、以下のように使用します。
$ java -Xmn160m -Xmx480m -Xms480m <クラス名>
最大ヒープ・サイズ(-Xmxで指定)に対するNEW領域の割合は、1/3から1/2が推奨される値です。NEW領域をより積極的に拡張したい場合は、1/2程度のサイズを指定します。
また、From領域とTo領域のサイズは、Eden領域のサイズに対する比率を指定して設定できます。具体的には、オプション-XX:SurvivorRatioを以下のように使用します。
$ java -Xmn120m -Xmx480m -Xms480m -XX:SurvivorRatio=8 <クラス名>
これにより、Eden領域 のサイズはFrom/To領域のサイズの8倍となります(From領域とTo領域のサイズは同じです)。上記の例の場合、NEW領域は96MB(8×12MB)のEden領域と、それぞれ12MBのFrom/To領域に分割され、これらの合計は120MBとなります。ちなみに、-XX:SurvivorRatioの値はデフォルトのままにしておくことが推奨されています。
チューニング結果の解析
ガベージ・コレクションのログ出力を実施すると、非常に大量のログが出力されます。このログをMS Excelなどの表計算ソフトに取り込むのも1つのテクニックです。これにより、時間の経過とともにNEW領域とOLD領域が増減する様子をグラフに描くことが可能です。またHPでは、HP JVM対応のチューニング・ツールHPjtuneを無償で提供しています(用語解説を参照)。
ここではHPjtuneによるログ解析の簡単な例として、Java ベンチマークプログラムの1つである「SPEC JBB2000」実行時のGCによるOLD領域の消費サイズ変化を観察してみます。
図4は、ヒープ・サイズのチューニングを行わずにSPEC JBB2000を実行した結果です。同図を見れば、OLD領域の消費サイズが200〜100MB程度の間を激しく上下していることが分かります。これはNEW領域が小さすぎるために短命なオブジェクトがOLD領域にあふれている状況を示しています。その結果Full GCが頻発し、そのたびにOLD領域の消費サイズが大幅に縮小するため、ノコギリ状のグラフとして表れます(なお、OLD領域の消費サイズが長期的な増加傾向にあるのは、SPEC JBB2000の特性によるものです)。
一方、図5は、JVMのオプション指定により、ヒープ・サイズのチューニングを実施した後の結果です。
図4と比較すると、GCの回数も減少し、OLD領域の消費サイズの急激な増加も見られません。これは、NEW領域やOLD領域の拡張、およびSurvivorRatioの変更などを実施したことにより、ヒープ・メモリが理想的な利用状況に調整されたことを示しています。
以上、今回はJavaにおけるガベージ・コレクションのメカニズムを解説し、JVMオプションの指定によるチューニング方法を説明しました。次回は、JVMのスレッドによるリソース競合の解消について解説する予定です。
用語解説
■HPjtune
JVMのガベージ・コレクション(GC)を解析するためのツール。JVMから得られたプロファイリング・データに基づきGCの状況を分析し、パフォーマンスの改善に役立つ情報を提供する。GC時のリソース利用状況や、アプリケーションのパフォーマンスにGCが与える影響のグラフ表示、またユーザーが解析対象として選択したメトリクスのグラフ表示が可能。詳細情報は、以下のページを参照。HPjtune(日本HP)
本記事は、HP-UX Developer Edgeに掲載された「連載 Javaパフォーマンスチューニング」を株式会社アットマーク・アイティおよび本記事の筆者が独自の判断のもとに加筆・修正したものです。
Copyright © ITmedia, Inc. All Rights Reserved.