先日行われた「第3回チューニンガソン(Tuningathon)」に参加して来ました。

僕は福岡在住なので、福岡サテライトでの参加です。

Zusaar 福岡サテライト

Zusaar 東京本会場

今回はblojsom + Tomcat + MySQLでした。

結果は5位。
仕事でTomcatを5年くらい運用管理している現役Java屋なので、
優勝しないといけない気がしますが。。。

福岡会場はJavaやった事がない方がほとんどで、
最近はホントにJavaって少数派なんだと実感しました。
なんか寂しい(ToT)
東京本会場はどうだったのかな?

条件は、

  • Tomcatをフロントにして、DBはMySQLにすること。
  • Tomcat, Java, MySQLの入れ替えはOK。
  • webapps/blojsom以下は改変NG。アプリ配置パスも変更不可。

という感じです。

僕がやった内容は以下になります。

  • JVMをJRockitに
  • JVMメモリ割り当てを調整
  • Tomcatを7に
  • Tomcatのserver.xmlのパラメータ調整
  • webapps以下はblojsomとmanager(Tomcatの管理コンソール)以外削除

自分の復習も兼ねて、チューニング内容などをまとめておきます。

■JVMをJRockitに
JRockit(ジェイロキット)とはBEA Systemsが開発したJVMです。
BEAはOracleに買収されているので、現在はOracleの製品になってます。
この記事がわかりやすいです。

BEA懐かしい。。。初めてJavaやった時のサーバはWebLogicでした。

仕事で使った事はなかったのですが、昔から早いと評判だったので使ってみました。

JRockitのJVMパラメータはOracleJVM(HotSpot)とちょっと違います。

OracleJVM(HotSpot)のパラメータの一部
JRockitのJVMパラメータ

SunがOracleに買収されてからJavaのページ構成が変わったので、
OracleJVM(HotSpot)の全パラメータの説明が載ってる公式ドキュメントが探しきれなくなってる。

■JVMメモリ割り当てを調整
指定したパラメータは、

-Xms:1408m  
-Xmx:1408m  

の2つだけです。
※ヒープ領域拡張のオーバーヘッドを防ぐため、-Xmsと-Xmxは同じ値にしましょう。

JRockitだとパラメータがだいぶ違うみたいで、OracleJVM(HotSpot)でいつも使っている
パラメータを設定すると起動すらしませんでした。
今回は時間も限られているので、JRockitのドキュメントを読むのはやめました。

いつもは、以下のパラメータあたりを設定してます。
※OracleJVM(HotSpot)の話です。JRockitでは違うかも。

JVMには大きく分けて3つのメモリ領域が存在します。
1. ヒープ領域
2. パーマネント領域
3. スレッドスタック領域

ヒープ領域の内部は更にNew領域、Old領域の2つに分かれます。
New領域の内部は更にEden領域、From領域、To領域の3つに分かれます。

この記事と、この記事がわかりやすいです。

・ヒープ領域の設定項目の代表的なもの
※他にもあります。

-Xms
-Xmx
-XX:NewSize
-XX:MaxNewSize
-XX:NewRatio
-XX:SurvivorRatio
-XX:TargetSurvivorRatio

・パーマネント領域の設定項目

-XX:PermSize
-XX:MaxPermSize

・スレッドスタック領域の設定項目

-Xss

今回は大きなアプリではないので、パーマネント領域、スレッドスタック領域は調整不要だったと思います。
-serverを指定した方がいらっしゃいましたが、Java6からはserverがデフォルトだった気がします。
公式ドキュメントは見つけられませんでした。。。

ヒープ領域の状態をグラフにするGCViwerというツールがあります。

-Xloggc
-XX:+PrintGCDetails

あたりのパラメータを指定します。

JVMパラメータはコマンドライン引数なので、
設定したパラメータがちゃんと反映されているかどうかは、psコマンドで確認できます。

こんな感じです。

tomcat   22113     1  0 Mar23 ?        00:04:12 /usr/java/default/bin/../bin/java -Xms1408m -Xmx1408m (長いので以降省略)

上記以外でパフォーマンスチューニングでやる事といえば、
プロファイラ、ヒープダンプ、スレッドダンプあたりでしょうか。
今回はやってません。。。

■Tomcatを7に
Tomcatはyumでインストールされてました。
yumでインストールした場合とアーカイブからインストールした場合で
フォルダやファイルの構成がちょっと違います。
以下のような感じです。

☆yumでインストールした場合
・インストールディレクトリ
/usr/share/tomcat6

・JVMパラメータ設定ファイルと変数
/usr/share/tomcat6/conf/tomcat6.conf
JAVA_OPTS変数

・Tomcatログファイル
/usr/share/tomcat6/logs/catalina.out

中身はこんな感じです。

$ ls -l /usr/share/tomcat6
合計 4
drwxr-xr-x. 2 root root   4096  3月 25 01:22 2012 bin
lrwxrwxrwx. 1 root tomcat   12  3月 25 01:22 2012 conf -> /etc/tomcat6
lrwxrwxrwx. 1 root root     23  3月 25 01:22 2012 lib -> /usr/share/java/tomcat6
lrwxrwxrwx. 1 root root     16  3月 25 01:22 2012 logs -> /var/log/tomcat6
lrwxrwxrwx. 1 root root     23  3月 25 01:22 2012 temp -> /var/cache/tomcat6/temp
lrwxrwxrwx. 1 root root     24  3月 25 01:22 2012 webapps -> /var/lib/tomcat6/webapps
lrwxrwxrwx. 1 root root     23  3月 25 01:22 2012 work -> /var/cache/tomcat6/work

シンボリックリンクでOS標準のディレクトリに配置されてます。
RHEL系はCATALINA_BASEとCATALINA_HOMEが同じディレクトリなので、
「/usr/share/tomcat6」以下にまとまってます。

Debian系はCATALINA_BASEとCATALINA_HOMEが別になっているので、
もうちょっと散らばっています。

☆アーカイブでインストールした場合
・インストールディレクトリ
任意

・JVMパラメータ設定ファイルと変数
以下のどちらか。
インストールディレクトリ/bin/catalina.sh
インストールディレクトリ/bin/setenv.sh
CATALINA_OPTS変数またはJAVA_OPTS変数
※setenv.shはアーカイブには含まれていません。
ファイルを作成すればcatalina.shから読み込まれます。

・Tomcatログファイル
インストールディレクトリ/logs/catalina.out

・init.dに配置する起動スクリプト
アーカイブでインストールする場合は自分で準備します。
今回はここを参考にさせてもらいました。

中身はこんな感じです。

$ ls -l
合計 112
-rw-r--r--. 1 root root 56797  2月 17 23:13 2012 LICENSE
-rw-r--r--. 1 root root  1192  2月 17 23:13 2012 NOTICE
-rw-r--r--. 1 root root  8826  2月 17 23:13 2012 RELEASE-NOTES
-rw-r--r--. 1 root root 10597  2月 17 23:13 2012 RUNNING.txt
drwxr-xr-x. 2 root root  4096  3月 25 02:34 2012 bin
drwxr-xr-x. 2 root root  4096  2月 17 23:13 2012 conf
drwxr-xr-x. 2 root root  4096  3月 25 02:34 2012 lib
drwxr-xr-x. 2 root root  4096  2月 17 23:11 2012 logs
drwxr-xr-x. 2 root root  4096  3月 25 02:34 2012 temp
drwxr-xr-x. 7 root root  4096  2月 17 23:13 2012 webapps
drwxr-xr-x. 2 root root  4096  2月 17 23:11 2012 work

■Tomcatのserver.xmlのパラメータ調整

enableLookups="false"
compressableMimeTypes="text/html,text/xml,text/plain,text/css,text/javascript"
compression="on"
maxKeepAliveRequests="2000"
<a href="http://tomcat.apache.org/tomcat-7.0-doc/config/http.html">HTTPコネクタのパラメータ</a>

この辺のパラメータは初めて設定しました。
実運用だとフロントにApacheとかを立ててAJPで通信するので、
Tomcatでは設定しないパラメータだと思います。

■webapps以下はblojsomとmanager(Tomcatの管理コンソール)以外削除
使っていないアプリは削除しないとメモリをムダに消費します。
blojsomとmanager以外は削除しました。

■その他チャレンジした事
・/etc/my.cnfを調整
MySQLをまともに触ったのが初めてだったので、色んなパラメータを適当に大きくしてみました。
素人がやっても効果は無かったです(ToT)
・MySQLを5.5に
rpmを取ってきてインストールした後、5.1の環境からダンプでデータを入れてみました。
mysqlクライアントからは繋がったのですが、アプリから繋がらなくなったので、元に戻しました。
原因不明です(ToT)

最後にスコアの推移を載せておきます。
スコアにバラつきが多い事に気づいたのがかなり遅かったので、
効果が無かったチューニングも多かったと思います。

■初期状態

[root@ip-10-154-31-26 3:18:09]# /home/ec2-user/bench.sh
166 fetches, 9 max parallel, 2.2654e+06 bytes, in 10 seconds
13647 mean bytes/connection
16.6 fetches/sec, 226540 bytes/sec
msecs/connect: 0.144114 mean, 0.427 max, 0.047 min
msecs/first-response: 522.831 mean, 1664.53 max, 118.706 min
HTTP response codes:
  code 200 -- 166
Score: 17.532 (get=16.600, comment=0.932(1), check=1.000)
Score sending was succeeded.

■JRockitにしてパラメータ調整した後

[root@ip-10-154-31-26 4:42:46]# /home/ec2-user/bench.sh
452 fetches, 9 max parallel, 7.37516e+06 bytes, in 10 seconds
16316.7 mean bytes/connection
45.1998 fetches/sec, 737513 bytes/sec
msecs/connect: 0.421542 mean, 61.588 max, 0.093 min
msecs/first-response: 187.649 mean, 662.327 max, 75.404 min
451 bad byte counts
HTTP response codes:
  code 200 -- 452
Score: 50.018 (get=45.200, comment=4.818(6), check=1.000)
Score sending was succeeded.

■Tomcat7に変更した後

[root@ip-10-154-31-26 5:52:18]# /home/ec2-user/bench.sh
541 fetches, 9 max parallel, 7.38303e+06 bytes, in 10 seconds
13647 mean bytes/connection
54.1 fetches/sec, 738303 bytes/sec
msecs/connect: 0.153067 mean, 1 max, 0.043 min
msecs/first-response: 156.761 mean, 550.082 max, 77.279 min
HTTP response codes:
  code 200 -- 541
Score: 55.083 (get=54.100, comment=0.983(1), check=1.000)
Score sending was succeeded.

■server.xmlを調整した後

[root@ip-10-154-31-26 7:39:09]# /home/ec2-user/bench.sh
467 fetches, 9 max parallel, 7.2862e+06 bytes, in 10 seconds
15602.1 mean bytes/connection
46.7 fetches/sec, 728620 bytes/sec
msecs/connect: 0.492951 mean, 91.456 max, 0.042 min
msecs/first-response: 183.904 mean, 958.097 max, 66.788 min
252 bad byte counts
HTTP response codes:
  code 200 -- 467
Score: 58.690 (get=46.700, comment=11.990(12), check=1.000)
Score sending was succeeded.

最後の計測の時は55秒台だったと思います。

MySQLとOS周りをもっと勉強して、次回また頑張ります!

■3/27追記
JITコンパイルについても理解しておいた方がいいと思うので、
わかりやすい記事へのリンクを追加しておきます。
Hotspot VMの基本構造を理解する