Olaf Heimburger著

Oracle Fusion Middlewareには疑わしいアプリケーション動作を調査するために、優れたツールセットが含まれています。

2010年1月公開

1995年にJavaが日の目を見て以来、Javaを使用して構築されたアプリケーションの複雑さは増す一方です。 この間、ますます複雑になる要件を克服するために多数のモデルやアーキテクチャが開発されてきました。 しかし残念なことに、ソリューションは使いやすくなるどころか、さらに困難で複雑になっています。 新しいコンポーネントが追加されるたびに待機時間が長くなり、ソリューションのパフォーマンスが低下しています。

パフォーマンスが低下した場合に必ず疑われるのが、使用されているテクノロジーです。 担当者の技術的背景によって、データベースとミドルウェアのいずれかが最初に疑われるでしょう。 通常、ネットワークやブラウザはほとんど疑われませんが、言うまでもなく、実証されない限りこれは偏った見方であり、ネットワークやブラウザが重大な影響 を及ぼす可能性を切り捨てることはできません。

パフォーマンス低下の本当の原因を突き止めるには、特定の使用プロファイルでアプリケーションを調査し、疑いの余地のない完全な証拠を提示する必要 があります。 幸いにも、Oracle Fusion Middlewareではこの作業を支援する各種ツールが提供されています。

疑わしい領域

パフォーマンスの低下には多くの原因が考えられます。 これから、アプリケーションのパフォーマンス低下を引き起こすもっとも一般的な原因の例を挙げます。

メモリ・リーク:メモリ・リークという用語は、少し誤解を招きやすい表現です。 コンピュータやJVMのメモリが水のように"漏れる"訳ではありませんが、使用可能なメモリが時間とともに期待値を下回ることに気付くでしょう。 なぜこのような現象が発生するのでしょうか。JVMガベージ・コレクタ(GC)が使用されていないオブジェクトをメモリから排除して、未使用メモリを再利 用するはずではないのでしょうか。 もっとも考えられる原因は、オブジェクトが未使用であるように見えないため、GCがメモリから排除できるオブジェクトを見つけられないということです。

ほとんどのメモリ・リークは、参照の見過ごしや実装の不十分な手製のキャッシュに起因します (ヒント:SoftReferenceやWeakReferenceを使用しない限り、GCによる自動的なキャッシュ縮小は利用できません)。 これらのリークによってGCの呼出し回数が増えるとともに、解放可能な少量のメモリを探す時間が長くなります。 その結果生じるアプリケーションのオーバーヘッドによって、ユーザー・エクスペリエンスに影響が及びます。 これらのメモリ・リークを特定し、排除することが、パフォーマンス・チューニングにおける一番の目標になります。

不適切なデータ・モデリング:データ・モデリングはアプリケーションの実行時動作に非常に大きな影響を与えま す。 最近の多層アプリケーションでは、データはプロセス境界を越えることができます。データが実際にプロセス境界を越える場合には、注意する必要があります。 境界を越えるには、バイナリ形式のデータを転送形式に変換する必要があるため、処理に時間がかかります。 しかし、このシリアライズとデシリアライズのプロセスが実装されていると、データをプロセス内にとどめた場合よりも応答が遅くなります。 データ型とプロセスの実装方法によって、全体的なパフォーマンスに重大な影響が及びます。

たとえば、通常、日付やタイムスタンプは64ビット値(JavaのLong型)として保存されます。 しかし、同じ情報をCalendar型 に保存することも簡単にできてしまいます。 一般に、Calendar型は80バイトの領域を占めます。 このため、適切なデータ型にタイムスタンプを保存することで、簡単に76バイトも節約できます。

次に、シリアライズではなく外部化を選択することで、劇的なパフォーマンス向上が得られる場合があります。 外部化のマイナス面は、開発中に、厳格なプログラミング手法によって追加のコストが必要になる点です。

ネットワーク経由の入力/出力の多用:ネットワーク・コンピューティングに対する大きな誤解の1つに、ネット ワークが"高速"であるという考えがあります。 何かをリモートで呼び出せば、間違いなく一定の時間が損なわれます。 ネットワーク・コールの回数やサイズを減らすことで、アプリケーションがその他の目的に費やす時間を節約できます。

ネットワーク時間は非常に簡単に節約できます。 たとえば、リモート・アプリケーションに処理を任せる方法があります。 通常、正しい結果を1つだけ返すような非常に具体的なコールは、何千もの不要な結果を返すコールよりも迅速に実行されます。

構成の不適切なJVM:すべてのJVMは、多数のコマンドライン・スイッチを介して構成され、その多くが直接的 または間接的にアプリケーションの実行時動作に影響を与えます。 たとえば、JVMメモリ(またはヒープ)サイズを定義するスイッチは、ほとんどすべてのJVMユーザーが知っています。 その他のスイッチはあまり知られていませんが、正しく設定することで特定の使用プロファイルにおけるパフォーマンスが向上する場合があります。ただし、使 用プロファイルが異なる場合、同じ設定によってパフォーマンスが低下する可能性もあります。

応答の遅いデータベース:データベースの応答が遅いというのは、多層アーキテクチャにおける誤った通念です。 むしろ、データベースはアプリケーション・アーキテクチャの全体像において常にもっとも高速な要素です。 その一方、索引が不足していると、パフォーマンスが劇的に低下する場合があります。 最適なアーキテクチャでデータベースを十分にチューニングし、SQL文を正しく使用すれば、優れたパフォーマンスが得られます。

最初に調査すべき領域について把握したら、次に何をすべきでしょうか。 疑わしい領域のいずれかに対して証拠を提供するには、適切なタイミングに適切なツールを使用することが重要です。 しかし、ツールについて確認する前に、Oracle Fusion Middlewareで使用できる実行時環境について確認していきましょう。

Oracle Fusion MiddlewareでのJava仮想マシン

構成のベースとしてOracle WebLogic Serverをインストールする際、ほとんどの場合、どのJVMを使用するかを選択できます。 この記事の作成時点で、WebLogic Serverが標準で提供しているのはSun JVM 1.6またはOracle JRockit JVM 1.6です。 それぞれのJVMに独自の特異性があり、適したアプリケーション・プロファイルも異なります。 使用するアプリケーションにもっともふさわしいJVMは、アプリケーション・プロファイルやJVMの処理方法によって異なります。 十分なテストやチューニングを通じて、アプリケーション・プロファイルに適したJVMを見つけることが重要です。

Sun JVM

Sun JVMはJavaのリファレンス実装であり、アプリケーションが期待どおりに動作することを検証するために使用されます。

Sun JVMのメモリ・モデルは、新世代旧世代という2つの主要なメモリ領域で構成されています。 また新世代自体が、1つのEden領域と2つのSurvivor領域に分かれています。 その他に、Permanent Generation領域(PermGenSpace)があります。

動的に作成されたオブジェクトは、はじめにEden領域に格納されます。 これらのオブジェクトはガベージ・コレクションによってSurvivor領域に移動され、次に旧世代領域に移動され、最後に使用されなくなると、ガベー ジ・コレクタに回収されます。 PermGenSpaceには、クラス、定数値、静的変数などの静的データが格納されます。

過度に小さなPermGenSpaceに対して、クラスや静的変数、および定数値のロードが多すぎると、SunのJVMはたちまちメモリ不足になり ます。 PermGenSpaceの領域は全体のヒープ・サイズから取得されるため、かなり小さい値に設定する必要があります。 旧世代領域が使用可能な領域の70~80%を継続して占めている場合、メモリ・リークが発生していると考えられます。 この割合が90%に達した場合、事態は深刻であり、ただちに調査する必要があります。

メモリが飽和状態に極めて近くなると、GCの呼出し回数が増え、回収できる領域を見つけるためのサイクルが長くなるため、実行時パフォーマンスに影 響が及びます。 これらの領域が小さ過ぎることは非常に多く、GCがメモリ要求を満たすにはさらにサイクル回数を増やす必要が生じます。 さらに事態が悪化すると、JVMがGC以外は実行できなくなり、アプリケーションがハングします。

Sun JVMにはさまざまなGCが含まれており、それぞれのGCに最適な使用プロファイルがあります。 利用できるGCについて、詳しくはJVMドキュ メントを参照してください。 GCとその動作は、コマンドライン・スイッチを使用してチューニングできます。

Oracle JRockit JVM

Oracle JRockit JVMはJavaと互換性を持つ実装であり、インテルのハードウェア向けの非常に高速なJVMとして設計および実装されています。 JRockitのメモリ・モデルはSun JVMのメモリ・モデルと互換性があり、新世代領域と旧世代領域を備えています。 新規オブジェクトや存続期間の短いオブジェクトは新世代領域に格納され、存続期間の長いオブジェクトは旧世代領域に格納されます。 Oracle JRockitメモリ・モデルにはPermGenSpaceがないため、PermGenSpaceがいっぱいになることでメモリ不足の例外がスローされる ことはありません。

Oracle JRockit JVMにもさまざまなGCが含まれています。 実行時のパフォーマンスを向上するには、特にMostly Concurrent MarkおよびMostly Concurrent Sweepや、Parallel MarkおよびParalle SweepといったGCを試してみると良いでしょう。 Sun JVMと同様、これらのGCはコマンドライン・スイッチを介して明示的に設定することもできますが、アプリケーションの使用プロファイルに対する最適な構 成に含まれている場合もあります。

ここまでで、Oracle Fusion Middleware JVMの背景について簡単に説明しました。次に、パフォーマンスの問題を診断するために提供されている基本的なツールセットの概要を確認しましょう。 選択したJVMによって、使用できるツールの組合せが異なります。

Oracle Enterprise Manager

パフォーマンスの問題を突き止める場合は、常にOracle Enterprise Manager Fusion Middleware Controlコンソールから開始します。 この管理ソフトウェアは、ほとんどのコンポーネントと同時にインストールされるため、すでに使用できる状態になっているかもしれません。 このソフトウェアを使用すると、アプリケーション実行時の状況に関する重要な情報が一目で確認できます。

Management ConsoleのSummary画面には、インスタンスの現在の状態に対するサマリーが表示されます。 Response and Loadグラフは別として、Summaryポートレットは詳しく確認する必要があります。 この非常に小さな画面に、有効な情報が表示されています。 サーブレット/JSP、JMS、EJB、JDBCに対するインジケータとJTA使用状況が表示されるため、これらの情報はあらゆるJava EEアプリケーションにとって非常に重要になります。

 

heimburger-tuning-f1
図1 Summary画面

 

サーブレットやJSPを多用しているアプリケーションでは、Most Requestedポートレット(下図)を確認すると良いでしょう。 異常に長い応答時間は、パフォーマンス低下の指標になります。

 

heimburger-tuning-f2
図2
Most Requestedポートレット

 

また、ログ・ファイルを軽視すべきではありません。 あらゆる問題の兆候を探す際に最初に確認すべき場所がログ・ファイルです。 ログ・ファイルの情報をその他の資料と適切に組み合わせることで、アプリケーションの実行時動作を簡単に把握できます。 次のスクリーンショットは、Log Messages検索ウィンドウを示しています。

heimburger-tuning-f3
図3
Log Messages検索ウィンドウ

 

VisualVMの使用

VisualVMJVisualVMはSun JVM向けのツールです。 JVisualVMはJDK 1.6.0_10以降のJDKに含まれていますが、VisualVMはスタンドアロン・アプリケーションとして単独でインストールできます。 またいずれもベースは同じであり、プラグインを使用して拡張できますが、VisualVMの方がより多くのプラグインに対応しています。 VisualVMはバージョン1.5.0以上のJDKに対して使用できますが、バージョン1.6.0を使用すると非常に効果的です。

すべての分析は、VisualVMコンソールから開始します。 このコンソールには、すべての実行時パラメータが非常に簡潔に表示されます(開始スクリプトを調べる必要はありません)。 「Monitor」 タブをクリックするだけで、JVMの現在の状況が表示されます。 詳しい情報は、Threads、Profiler、Memory Sampler、Visual GCなどのタブから確認できます。

 

heimburger-tuning-f4
図4 VisualVM Consoleウィンドウ

 

Threadsタブには、JVM内で現在使用されているすべてのスレッドが表示されます。 「Thread Dump」 ボタンをクリックするとスレッド・ダンプが作成され、Thread Dump Analyzerプラグインを使用した分析で使用できます。

 

heimburger-tuning-f5
図5 VisualVMのVisualGC

 

VisualGC:Sun JVMのメモリ・モデルに関する問題を見つけるには、VisualGCプラグインを使用します。 JDK 1.5.のjvmstat 3.0に同梱されているVisualGCツールに基づくこのプラグインは、JVMのオンライン状況に加えて、クラス・ローダー時間、コンパイル時間 (JITの場合)、GC時間をを表示します。 一定期間後にアプリケーションのパフォーマンスが低下する傾向にある場合、VisualGCを使用してJVMメモリを調査することを検討してください。

 

heimburger-tuning-f6
図6 VisualVMのThreadsタブには、すべてのスレッドの状態が表示されます

 

Memory SamplingとHeap Dumps:使用可能なメモリがオブジェクトによってどのように使 用されているのかを分析するために、2つのツールが提供されています。 Memory Samplerはオンライン・ビューを提供し、Heap Dump Analyzerはメモリのオフライン・ビューを提供します。 ボタンを押すだけで、いつでもヒープ・ダンプを作成できます。 VisualVMによって自動的にこのダンプが読み取られ、次のような結果が表示されます。

 

heimburger-tuning-f7
図7 Heap Dumpの結果

 

Oracle JRockit Mission Control

提供されたOracle JRockit JVMを使用してOracle Fusion Middlewareを実行している場合、追加のインストールなしでOracle JRockit Mission Controlを使用できます。

VisualVMの場合と同様に、分析は常にJRockit Consoleから開始します。 このコンソールにはJVMの現在の状態のサマリーに加えて、使用されているJava Heap、使用されている物理メモリ、CPU使用率、ライブ・セットに対するゲージと、使用されているメモリとプロセッサに対するグラフが表示されます。 さらに詳しくアプリケーション・プロファイルを把握するには、Memory、Threads、Runtime、Exception Count、Memory Profileといったタブを利用します。

 

heimburger-tuning-f8
図8 Oracle JRockit Mission Control Console

 

Oracle JRockit Runtime Analyzer(JRA)は現在Mission Controlに完全に統合されており、アプリケーションの実行時動作をオンデマンドで記録するために使用されます。 メモリ・モジュールの置換やアスペクト・ウィービング、または固有の共有ライブラリなど、特別な手段は必要ありません。 またオーバーヘッドはわずか1~2%に抑えられています。

JRAを利用すると、アプリケーションのスナップショットを得ることができます。 提供される情報には、応答の遅いメソッドやメモリ使用状況、すべての既存オブジェクト、考えられる最適化、ブロッキング・スレッドなどが含まれます。

 

heimburger-tuning-f9
図9 Oracle JRockit Mission ControlのTop Hot Methods

 

Memory Leak Detector:潜在的なメモリ・リークを発見するには、Memory Leak Detectorを使用します。 オンデマンドで起動すると、潜在的なメモリ・リークの傾向が即座に表示されます。 しばらくすると、実際のリークを発見し、疑わしいクラスを調査できるようになります。

 

heimburger-tuning-f10
図9 Memory AnalyzerのTrend Analysisは潜在的なメモリ・リークを表示します

 

結論

Oracle Fusion Middlewareには疑わしいアプリケーション動作を調査するために、優れたツールセットが含まれています。 これらのツールはおもに一時的な使用を意図しており、継続的な監視を目的としたものではありません。 また、すべてのコンポーネントの全体像を把握するには、より完全なビューが必要になります。この場合、Application Diagnostics for Java(AD4J)またはOracle Realtime User Experienceを使用すると良いでしょう。

アプリケーションを調査する場合、問題の原因となるアプリケーション・プロファイルを再現するテスト・ケースを使用する必要があります。 完全なアプリケーションの全体像を収集するには、これらのテスト・ケースを何度も実行します。

アプリケーションをチューニングする場合、1つの手段を講じるごとにテストを実行し、その効果を測定します。 期待どおりの結果が得られない場合は、元に戻して別の手段を試します。 この作業には時間がかかりますが、最終的に、アプリケーション・プロファイルに合わせてチューニングされた環境を構築することができます。



Olaf Heimburger
[blogs.oracle.com/olaf]はオラクルのコンサルタントであり、おもな専門分野は、 Java、ミドルウェア、SOA、およびセキュリティです。