ServletFilterとの連携成功
S2JmxJavelinですが、無事(やっと?)、ServletFilterとの連携に成功しました。
(FilterとInterceptor、両方から使えるように中改修が必要だったのです。)
で、見た目はこんなになります。
(平均処理時間が長いのはデバッグしながら動作させたため。)
これで、パフォーマンスに問題のある箇所がページ単位でわかるようになります。
ちなみに、S2JmxJavelinでは検出した処理時間を記録するための閾値を設定できるようにしていますが、この閾値の使い方を次バージョンではちょっと変えます。
今までは、
- 個々のメソッド呼び出し毎に閾値を見て判断
していたのが
- メソッドのコールツリーのルートで判断
に変更になります。
ServletFilterと組み合わせると、
- 7秒ルール(って懐かしい響きですが)を超えたアクセスを記録
とか、できるようになります。
・・・早く完成させたい。
Javaの中のシグナル
straceやtrussでJavaVMの挙動を調べると、頻繁にSIGSEGVが発生していることがわかります。
で、SIGSEGVが発生しても正常に処理を継続する場合と、abortしてしまう場合とがあって、
どういう理由で分かれるのかが以前から疑問だったのですが、最近、やっと分かりました。
(詳しくはhttp://sdc.sun.co.jp/java/j2se/private/jdk50_ts_guide-jp.pdfを参照)
どうやら、HotSpotコンパイラの最適化機能によって、ポインタのNULLチェックが省略されているようです。
この場合、SIGSEGVが発生すると、内部でNullPointerExceptionに変換されてthrowされる事になります。
HotSpotコンパイラが生成したコード以外の場所でSIGSEGVが発生した場合、Java VMは致命的エラーログ(hs_err[PID].logっていうファイル)を出力して終了します。
逆に言うと、「NullPointerExceptionの裏では"Segmentation Fault"が発生している」、という事ですね。
やっぱりNullPointerExceptionなんて、起こすもんじゃないな、と。
他にもSIGBUS、SIGFPEなどもJava VM内部での制御に使用しているとの事。
これらのシグナルのハンドラを書き換えているプログラムをJavaから呼び出すのは、やめておいた方が良いですね。
それでもシグナルハンドリングをしたい人は、「シグナル連鎖機能」なるものを使え、と書いてあります。
どういうものかは私も知らないのですが、そのうち、試してみたいところです。
次回追加機能
一区切りついたところで、次の機能追加を考えています。
今のところ、
- 処理時間をレイヤ毎に分割
- 統計処理を行うMBeanを追加する
- S2JmxJavelinと連携するServletFilterを提供
の順に取り組む予定です。
1についてですが、例えば、現状だと
Action→Logic→Dao
という呼び出し関係があった場合、処理時間を以下のように累積で出力しています。
Action(100ミリ秒) → Logic(80ミリ秒) → Dao(60ミリ秒)
と表示します。
これだと、Daoで一番時間がかかっているはずが、
ちょっとわかりづらいので、
Action(20ミリ秒) → Logic(20ミリ秒) → Dao(60ミリ秒)
といったように、レイヤで消費した時間を出力するように変更します。
ボトルネックをより簡単に見つけられるようになると思います。
2はHttpAdaptorからでも容易にボトルネックが見つけられるようにするための措置です。
3はHTTPリクエストを受信してからActionが呼び出されるまでの時間を計測できるようにすることが目的です。
Viewerの方は問題のあるメソッドの表示を赤くするなどして、より問題箇所を切り分けやすくしたいと考えています。
公開は3/21を目標にしています。
Viewer豆知識 No. 1
S2JmxJavelinViewerでクラスを選択すると、
プロパティ・ウィンドウに詳細情報が表示されます。
一度お試しあれ。