nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

JBoss AS 7のJava VMチューニング

JBoss Advent Calendar 2011の15日目のエントリです。JBoss AS7 はじめの一歩で少し書いたんですが、だいぶ古くなっているのと少々解説を。今回はJBoss AS 7.1.0.Beta1とFedora 16のOpenJDK 6 64bitを利用します。

$ java -version
java version "1.6.0_22"
OpenJDK Runtime Environment (IcedTea6 1.10.4) (fedora-61.1.10.4.fc16-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode)

チューニングしていない状態

JBoss AS 7.1.0.Beta1の出荷時のJava VMオプションは$JBOSS_HOME/bin/standalone.confに定義されており、以下のようになっています。JBoss ASではstandalone.shで-serverオプションが自動的に付与されるようになっています。

JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000"
JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"

起動してみます。1.4秒ですね。

JBoss AS 7.1.0.Beta1 "Tesla" started in 1422ms - Started 125 of 186 services (60 services are passive or on-demand)

チューニングする

変更したオプションはこんな感じになっています。

JAVA_OPTS="-Xmn128m -Xms512m -Xmx512m -XX:MaxPermSize=256m -Xss512k"
JAVA_OPTS="$JAVA_OPTS -Xverify:none"
JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC"
JAVA_OPTS="$JAVA_OPTS -XX:+TieredCompilation"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCompressedOops" # 64bit only!
JAVA_OPTS="$JAVA_OPTS -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000"
JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"

起動してみると1.2秒くらいに縮まりました。15%-20%くらいの速度向上、というところでしょうか。

JBoss AS 7.1.0.Beta1 "Tesla" started in 1228ms - Started 125 of 186 services (60 services are passive or on-demand)

基本的に最近のJava 6/Java 7のVMは昔ほど細かいチューニングをしなくてもパフォーマンスが良いです。というのも、既知のほとんどのパフォーマンス系オプションがデフォルトでtrueになっています。もうオプションをごちゃごちゃ覚えたり指定する必要はほぼないでしょう。

オプションの調べ方

オプションの一覧とそのデフォルト値は-XX:+PrintFlagsFinalオプションで取得できます。655個のオプションが表示されます。-XX:+UnlockDiagnosticVMOptionsとかも指定すると724個。

$ java -XX:+PrintFlagsFinal 2>/dev/null | less

例えばDoEscapeAnalysisのデフォルト値を見たい、という場合はgrepすれば良いです。

$ java -XX:+PrintFlagsFinal 2>/dev/null | grep DoEscapeAnalysis
bool DoEscapeAnalysis = true {C2 product}

この記事で利用しているオプション

さて、指定しているオプションの解説を。

  • -Xmn128m -Xms512m -Xmx512m -XX:MaxPermSize=256m -Xss512k
    • メモリとスタックサイズの指定。スタックサイズはデフォルト1024kですがそんなに使うことはまれなので512kに下げています。
  • -Xverify:none
    • クラスベリファイヤを無効化します。クラスベリファイヤが有効化されている場合、クラスをロードするときに不正なクラスをチェックして、不正なクラスがあった場合はVerifyErrorを出力します。現在のモダンなJavaコンパイラは不正なクラスを吐くこともありませんし、ネットワーク上からクラスをロードするようなユースケースも多くはないでしょう。クラスファイルレベルでは信頼できる状況がほとんどだと思いますし、そのような状態でクラスベリファイアを毎回走らせる意味はあまりありません。VerifyErrorを見たことがない、というような環境では有効化しても単にパフォーマンスが遅くなるだけです。ディスク障害などでクラスファイルが壊れる、というような可能性は無くはないので、本番環境などでは有効化しておいたほうが良いです。
  • -XX:+UseConcMarkSweepGC
    • CMS(コンカレントマークスイープ)GCを有効化します。JBoss ASはサーバなので、Full GCで何秒か止まる、という性格の標準のスループット重視GCより、レスポンスタイムにムラのないCMSのほうが良いです。テキスト処理などのバッチ処理は途中でストップザワールドが起きても誰も気にしないので通常のGCで良いと思いますが、オンライン処理はCMSを使うほうが良いでしょう。
  • -XX:+TieredCompilation
    • スタートアップの早いHotSpot Client VM(-clientオプション)とスタートアップは遅いけどよりハイレベルな最適化を行うServer VM(-serverオプション)の両方の特性を受けられる段階的コンパイルを有効にするオプションです。
  • -XX:+UseCompressedOops
    • 64bit専用オプションで、圧縮OOP(Ordinary Object Pointer)を有効化します。メモリ消費が抑えられます。
  • -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError
    • メモリのモニタリングとトラブルシューティングのための基本的なオプションたち。
  • 残りの-Dのやつら
    • 消したり変えたりする必要が基本的に無いJBoss ASのおまじない

32bitではUseCompressedOopsの行を削除すれば良いです。