その環境で後々本番運用もするつもりだから、メモリチューニングを今のうちにしておこう。
で、setenv.shを作ろうと思ったのだが、久々過ぎてパラメータの意味を忘れてしまってた。
今後もチューニングの機会はあるだろうし、自分なりにまとめておこう。
ヒープサイズのオプション
-Xms
Javaヒープ全体の初期メモリサイズ
-Xmx
Javaヒープ全体の最大メモリサイズ
-Xss
スレッドスタックサイズ
XmsとXmxは同じサイズを指定しておくと,ヒープエリア管理のオーバヘッドを削減できる可能性がある。
JavaヒープはNEW領域と、OLD領域に分かれる。
NEW領域
新しいオブジェクトを格納する領域。デフォルトでの起動時のサイズは2MB、最大サイズは16MB。
OLD領域
古いオブジェクトを格納する領域。デフォルトでの起動時のサイズは4MB、最大サイズは48MB。
OLD領域はアプリが必要とするメモリ+NEW領域分のメモリサイズが好ましいようだ。
OLD領域がいっぱいになるとFull GCが発生する
ある記事で、XX:NewSizeとXX:MaxNewSizeをヒープサイズ全体の30%から25%に設定したときが最も高いパフォーマンスを得ることができたと読んだ。
よって、NEW : OLD = 1 : 2程度が好ましいと思われる。
NEW領域と、OLD領域関係のオプション
割合か、サイズで指定。(どっちも設定した場合はどうなるのかは不明)
-XX:NewRatio
New領域に対する Old領域の割合を設定。2を設定した場合は、New領域とOld領域の割合が、1:2になる
-XX:NewSize
Javaヒープ全体の内のNew世代領域のサイズ
-XX:MaxNewSize
Javaヒープ全体の内の最大New世代領域のサイズ
NEW領域内はさらに「Eden」「Survivor(From)」「Survivor(To)」に分かれる。
Eden領域
新しいオブジェクトが作成された際に最初に配置されるメモリ領域。
Survivor領域
Eden領域が満杯でGCされる時、まだ参照されているオブジェクトを保持する領域。
オブジェクトが不要になるまでの間、From領域とTo領域を行ったり来たりする。
行ったり来たりの流れでその回数がカウントされるらしい。
その回数がMaxTenuringThreshold(df=32)というしきい値を超えるとOLD領域に移動される。
または、Survivor領域がいっぱいになってもOLD領域に移動される。
Eden領域、Survivor領域関係のオプション
-XX:SurvivorRatio
New世代領域内のEdenとSurvivorの比率。8を設定した場合は、EdenとSurvivorの割合が、8:1になる
アプリを動作させて使用状況を確認しながら設定すべき値を探るのが好ましいようだ。
-XX:TargetSurvivorRatio
Survivor領域がいっぱいと判断される使用率。これを超えるとOLD領域に移動する。
Javaヒープ以外に、Permヒープというのもある。
Permヒープ領域
APサーバーや、その上で動作する業務プログラムのクラスやメソッドなどのメタデータが格納される領域。
要は、JavaVMにロードされるクラス・ファイルの合計値。
この領域が不足するとAPサーバーがダウンするらしい。。。
でも、多くの場合全てのクラスがロードされることは少ないから、通常は初期値で問題ない。
その他オプション
-Djava.awt.headless=true"
サーブレットで画像を処理させるときの設定(J2sdk1.4以上)
あんまり調べてない。
以上を踏まえてTomcatのsetenv.shに設定するとき。
利用できるメモリを考慮して、
#!/bin/sh
XXMS="512M"
XMX="512M"
XSS="256k"
NEWRATIO="2"
SURVIVORRATIO="8"
TARGETSURVIVORRATIO=80
JAVAENV="java.awt.headless=true"
JVM_OPT="-d32"
export CATALINA_OPTS="-server -Xms${XMS} -Xmx${XMX} -Xss${XSS}
-XX:NewRatio=${NEWRATIO}
-XX:SurvivorRatio=${SURVIVORRATIO}
-XX:TargetSurvivorRatio=${TARGETSURVIVORRATIO} -D${JAVAENV} ${JVM_OPT}"
とかでやっている。