「Javaの鉱脈」でJVMオプションの記事を書きました
WEB+DB PRESSのVol.82に、かなり気合いの入ったJVMオプションの記事を書いたので、是非読んで頂きたい。
2014/8/23発売ですので、既に購入頂いてる方も多いと思います。
電子書籍版もありますので物理的な媒体に興味がない方はPDFを買って下さい。
今回の記事における対象読者について
今回の記事は、ターゲットとしてJavaに余り時間をコミットしていないけども便利なのでJVM上で動くアプリケーションをウッカリ運用している人をイメージしながら書きました。
例えば、OSSものだとHadoopやZooKeeper、LuceneやSolr、商用製品だとStashとかJIRAとかconfluenceとかそういうものですね。
僕の観測範囲だと、PHPやPerlの様なスクリプト言語からScalaへ移行している人々を見かけますが、そういう人たちは多分きっと負荷テスト中であるとか、アプリケーションのリリース後に謎のパフォーマンス劣化に襲われて無我夢中でGoogle先生から得られる情報を元にJVMのオプションをガチャガチャと弄ってるんじゃないかなぁ…と想像しています。
今回の記事は、そういった時に調査の足がかりとなるような知識になればイイなぁと考えています。
前半部分ではJVMのメモリモデルの話とGCのアルゴリズムの話。それだけだと実効性に乏しいので後半部分では具体的な値を伴うオプションの話を書いています。
特にGCのアルゴリズムを説明するにあたって、GCログにでるメッセージを読めるようにキーワードとなる単語をあえて和訳せずに書きました。興味をもったら公式のブログにおけるGCログの話も読んで下さい。
https://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs
https://blogs.oracle.com/poonam/entry/understanding_g1_gc_logs
これでも内容的には不足がある実務者の皆様は、公式のチューニングガイドが昨日リリースされましたのでじっくり読むと良いでしょう。
書籍になっており、かつより読み易いガイドとしてはJava Performance: The Definitive Guideをお勧めします。
-XX:+UseLargePages については書くかどうか迷いましたが、動作検証が間に合わなかったので書きませんでした。6GB以上のメモリをJVMに割り当てて運用している皆様は是非お試し下さい。OS側の設定がいくつか必要なので若干面倒なのですが…。
JVMのオプションを一覧化するツールについて
今回の記事は、当初重要なオプションの変更や追加、廃止にもっとフォーカスした記事にしようとしていたので、オプションを一覧化するツールを作りました。
このツールはOpenJDKのソースコードリポジトリからコードをダウンロードした上で、cppのコードを正規表現を駆使して解析します。このツールで作ったデータはcompare JVM optionsにて公開しています。
表の見方は何となく分かるとは思いますが一応説明しておきます。
-
name
- オプションを設定する際に利用する名前です
-
description
- 当該オプションの説明です
-
type
- どんな範囲の値を当該オプションに設定できるのか決めるオプションの型です。C++の型ですが、何となく類推して下さい。
-
6,7,8
- JVMの各バージョンで当該オプションがサポートされているなら o 。サポートされていないなら x です。
-
6.default,7.default,8.default
- JVMの各バージョンにおける当該オプションの静的に決まるデフォルト値です。
- 実行環境や他のオプションとの兼ね合いで決まる値もあります。
- hotspot/file/src/share/vm/runtime/arguments.cpp辺りを読むとエルゴノミクスによって決まる値をある程度類推できます。
-
kind
- オプションがどのような状況で使えるのかを表す種類です。 notproduct や develop のオプションはリリースバイナリには含まれていません。
-
file
- オプションが定義されていたファイル名です。
- オプションが定義されていた場所によって、どのような目的のオプションなのかある程度類推できます。
- 例えば、share/vm/gc_implementation/g1/g1_globals.hpp ならG1GC用のオプションです。
このツールに関する雑感
JVMはプロダクションビルド以外で、-XX:+PrintFlagsWithCommentsを付けて起動するとオプションの一覧が説明付きで標準出力されるのですけども、これだとプラットフォーム依存性のあるオプションが全部は出てこないのですよね。
JVMのオプションは公式にメンテナンスされている一覧が存在しないし、一覧を探して出てくる情報がどれもこれも古い上に、どうやって作ったのか分からない代物ばかりなので自分で作りました。
最初は手元にあったJava8のソースコードだけをパーズしていたので、コードを自動でダウンロードしてはいなかったのですけども、Java6とJava7との差分が欲しくなったりだとか、特定バージョンのコードが欲しくなったりだとかを繰り返しているうちに自動でダウンロードしないと話にならん感じがしたのでGradleでダウンロードするようにしました。
java.netのリポジトリの負荷が高いのは、こういうアクセスも結構あるせいなんじゃないかなぁ…とか思っています。
JSONが出力できるのですけども、これは当初解析したオプションをこねくり回すのを手元にあるJSONベースのドキュメントデータベースでやっていたからです。Google Spreadsheetにインポートする為にCSV形式で出力するようにしました。
コードベースとしてはRxJavaとStream APIが混ざってて気持ち悪い感じになっていますが、これはコードを書いた時期が随分ズレていたからです。どちらかに統一しようと思えば出来なくは無いと思いますが、雑に書いたツールなので、これ以上あまり頑張れません、PR頂ければマージします。