スラッシュドット    はてなブックマーク  Yahoo!ブックマークに登録  印刷
「現場から学ぶWebアプリ開発のトラブルハック」連載一覧へ
現場から学ぶWebアプリ開発のトラブルハック 第12回


アプリ開発でも、よ〜く考えよう。
キャッシュは大事だよ


佐藤聖規
2008/10/15

本連載は、現場でのエンジニアの経験から得られた、APサーバをベースとしたWebアプリ開発における注意点やノウハウについて解説するハック集である。現在起きているトラブルの解決や、今後の開発の参考として大いに活用していただきたい(編集部)

“無駄”より“遅い”ものはない

今回の主な内容
無駄”より“遅い”ものはない
先入観は判断を鈍らせる
キャッシュは、ためるもの
  ではなく使うもの
過ぎたるは及ばざるがごとし
怠惰(Lazy)に問題を解消
ご利用は計画的に

 今回もパフォーマンスにまつわるトラブルをハックするが、アプリケーションのパフォーマンスチューニングで最も有効な手段は「処理を行わない」ことである。何もしないことに勝る高速化は存在しない。今回のトラブルでは、インスタンスキャッシュ化して、無駄な処理を行わないことでチューニングを行う手法を紹介する。

 しかしながら、往々にしてチューニングはトレードオフである。そのトレードオフが引き起こす、さらなるトラブルを紹介する。

コンサルティングもトラブルハッカーの仕事

 とあるプロジェクトから1通のメールが届く。

 「あるJavaで作成したリッチアプリケーションのパフォーマンスに問題を抱えている。自分たちで考えられ得る対策は講じた。しかし、目標のパフォーマンスを達成できない」とのことで、相談に乗ってほしいそうた。

 こういったケースをメールでやりとりしても“らち”が明かないため、早速現場へ急行する。トラブルが発生した場合に何をするべきなのか、が分からないプロジェクトは多い。そんなプロジェクトのコンサルティングを行い、進むべき道を示すのもトラブルハッカーの仕事である。

まさかXMLが

 早速現場の担当者にヒアリングを行う。今回パフォーマンスが出ていないシステムはJavaリッチアプリケーションであり、サーバとクライアントの間の通信をXMLで行っている(図1)。

 
図1 samuraiの真っ赤な画面
図1 システム構成

 また、これまでの調査では、サーバ側の処理はさほど速度が遅くはなく、クライアント側の処理がボトルネックになっているとのことであった。

 SOAPに代表されるXMLを用いて通信を行うシステムでは、XML操作に関する以下の処理がボトルネックになりやすい。

  • XMLのパース
  • XMLとJavaオブジェクトのマッピング

 XMLの取り扱いには苦い思い出があるため、真っ先に担当者へ確認をしたがXMLに関しては「すでに以下のようなチューニングを施した」と伝えられた。

  • XML入れ子構造の簡略化
  • 操作差分分のXMLだけを送信するように修正

先入観は判断を鈍らせる

 先入観を持つと視野が狭くなって、問題の本質を見失ってしまう。再び冷静になり事態を整理する。

  • GCの頻度はさほど高くない
  • 通信が発生する操作を行うとCPU利用率が急上昇する

 以上から、本連載第1回「Webアプリの問題点を「見える化」する7つ道具」のトラブル切り分けフローに基づき、メソッドプロファイラの導入を決定して、処理時間がかかっているメソッドを特定することにした。

プロファイラは、何でもお見通し

 早速、フローの手順3「メソッドプロファイリング」に基づき、あるメソッドプロファイラをアプリケーションにアタッチして、どのメソッドがボトルネックなのかを確認した。

 また、結果を平均化するため通信を行う操作を10回繰り返したときの結果をプロファイリングした。プロファイリングの結果は図2のとおりである。

図2 2重ロックのシーケンス図
図2 プロファイリングの結果(一部を再現したものです)(画像をクリックすると拡大します)

 一見すると、普通のプロファイリング結果であるが、よく見てみると大きな問題に気が付く。

 そう、「getInitBillingProps」メソッドの呼び出し回数が実行回数の10回と一致しているのだ(図2の赤枠参照)。

 名前から推測するにアプリケーション初期化のためにプロパティファイルのロードを行い、プロパティの値をインスタンス化しているようである。メソッドの名前どおりの動作を行っているとすれば、アプリケーションの通信の操作を10回繰り返したからといって、「getInitBillingProps」メソッドが10回実行されるのは明らかにおかしいはずである。

「getInitBillingProps」メソッドの挙動を確認

 まずは、ソースを確認する。やはりプロパティファイルからプロパティの値をオブジェクト化しているだけである。念のため、忙しそうにしている担当者を捕まえて、メソッドの仕様の確認をした。やはり「getInitBillingProps」メソッドはアプリケーションの初期化のためにプロパティの値をインスタンス化するためのメソッドらしい。

図3 通信時の挙動
図3 通信時の挙動

 すなわち、このアプリケーションは通信を行うごとにプロパティファイルにアクセスしていることになる。つまるところ、完全に無駄な処理を行うのである。これでは、パフォーマンスが出るはずもない。

 では、こういった状況ではどのような解決策があるのか? 読者の皆さんも考えてみてほしい。次ページで、その回答例を提示しよう。

1-2

Index
第12回 アプリ開発でも、よ〜く考えよう。キャッシュは大事だよ
Page1
無駄”より“遅い”ものはない
先入観は判断を鈍らせる
  Page2
キャッシュは、ためるものではなく使うもの
過ぎたるは及ばざるがごとし
怠惰(Lazy)に問題を解消
ご利用は計画的に



Java Solution全記事一覧


Java Solution フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

スキルアップ/キャリアアップ(JOB@IT)

- PR -
@IT Sepcial
- PR -

お勧め求人情報

キャリアアップ 〜JOB@IT
@IT Sepcial
ソリューションFLASH