「現場から学ぶWebアプリ開発のトラブルハック」連載一覧へ
現場から学ぶWebアプリ開発のトラブルハック 第12回


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


佐藤聖規
2008/10/15


キャッシュは、ためるものではなく使うもの

 今回のトラブルの最大の原因は通信を行うごとに、値のまったく変わらないプロパティファイルにアクセスしてしまうことである。

 そこで今回は、一度必要なプロパティの値をオブジェクト化したら、ロードしたプロパティをキャッシュ化しておき、2回目以降の通信時にはキャッシュから値を取得する形に変更することに決定した。

図4 キャッシュ化した後の通信時の挙動
図4 キャッシュ化した後の通信時の挙動

 なお、このアプリケーションでは、プロパティファイルは更新されないため、キャッシュクリアや更新のためのキャッシュアルゴリズムは特に用いず、アプリケーションが終了するまでキャッシュを保持しておくこととした。

 つまり、GOFのデザインパターンでいうところのシングルトンパターン(注意:シングルトンパターンの詳細な解説は「クラスのインスタンスを1つに保つ(Singletonパターン)」を参照してください)の適用を勧めた。

 私はプロジェクトの開発者たちにに修正のアドバイスをして現場を立ち去った。

トラブルハッカーはアドバイスがほとんど

 なお、私たちのようなトラブルハッカーはプロジェクトのメンバーではないことが多い。そのためプロジェクトのアーキテクチャや業務に精通しているわけではない。

 従って、問題点を解消するためのアドバイスだけで実際のソースコードの修正や再試験はプロジェクトに任せることがほとんどである。

ところが、問題再発!?

 問題特定から数日が経過して、私は問題が解決したか気になりながらも、平和な日々を過ごしていた。「便りがないのは元気な証拠」といわんばかりに問題が解決したプロジェクトからは連絡がないことが多い。

 そう思っていた矢先、再びプロジェクトの担当者から電話がかかってきた。何でも、通信時のパフォーマンスは目標を達成したらしいが、それとは別の問題が発生したらしい。

 とにかく電話では現状が伝わってこないため、再びプロジェクトへお邪魔してヒアリングを行うことにした。

過ぎたるは及ばざるがごとし

 プロジェクトは以前の分析結果に基づき、プロパティファイルのインスタンスをキャッシュ化した。しかし、また別の問題が発生してしまったらしい。

再発した2つの問題

 プロジェクトの担当者にヒアリングを行ったところ、以下の2点が判明した。

  • 通信時のパフォーマンスは目標を達成した
  • アプリケーションの起動が著しく遅くなってしまった

 なお、ソースコードの修正は「プロパティインスタンスのキャッシュ化のみの修正」を行ったらしい。

 上記の事実と現象から原因は、プロファイリングを行うまでもなく、容易に予想がついた。恐らく、起動時にプロパティファイルをキャッシュ化する処理を実施しているのだろう。

起動時のプロパティファイルのキャッシュ化に加え……

 早速、担当者に確認したところ、やはり起動時にプロパティファイルのキャッシュ化を行っているらしい。さらに、以下の事実が判明した。

  • プロパティファイルは業務種別ごとに分かれており、全部で10個以上ある
  • 1つのプロパティファイルは数メガバイトから数十メガバイトの大きなサイズである
図5 起動時にすべてのプロパティをキャッシュ化する方式
図5 起動時にすべてのプロパティをキャッシュ化する方式

 上記の処理を起動時にすべて行ってしまっては、アプリケーションの起動が著しく遅くなってしまうのは無理もない。まさしく、「過ぎたるは及ばざるがごとし」である。

なぜ起動時に?

 ここで1つの疑問が浮かんだ。「なぜ、起動時にすべてのプロパティファイルをキャッシュ化したのか」である。

 この理由は、サーバ側のパフォーマンスに問題がなかったのは、起動時に必要なプロパティファイルをすべてインスタンス化して再利用していたからであり、その仕組みを踏襲したとのことである。

怠惰(Lazy)に問題を解消

 起動時にすべてのプロパティをキャッシュ化する方式は、一度起動すればメンテナンスのとき以外は再起動をしないサーバ型のアプリケーションでは有効な手段だといえる。

 ただし、今回は必要なときだけ起動して、不必要になればアプリケーションを終了するクライアント側で動くリッチアプリケーション型のアプリケーションである。起動が著しく遅くては、ユーザーへ与えるストレスが大きくなってしまう。

 そこで、プロパティファイルをインスタンス化するのは、初めてプロパティの値が使われるタイミングとした。すなわち「Lazy Instantiation(怠惰なインスタンス化)」である。

図6 Lazy Instantiationによるキャッシュ化
図6 Lazy Instantiationによるキャッシュ化

 つまり、起動時は「何もしない」というチューニングを施すこととなる。

意欲的なインスタンス化もある

 なお、この起動時にすべてのインスタンス化を行うような手法を「Eager Instantiation(意欲的なインスタンス化)」といい、起動時間にさほど気を使わず、比較的簡単にメモリを増設可能なサーバ型のアプリケーションでは有効な手法といえる。

 これにより、初めてプロパティの値が利用されるときは処理が遅くなってしまうが、起動時の著しいパフォーマンスの低下は抑えられる。

 すべてのプログラムを修正すれば、抜本的な対策を行えるかもしれないが、もちろんそんなことをやっている時間はない。このように、チューニングは往々にしてトレードオフである。

 そしてLazy Instantiationを行うことで、ようやくプロジェクトは目標のパフォーマンスを達成できた……。

ご利用は計画的に

 今回についてまとめると、以下の3つのテクニックでチューニングを行うトラブルハックを紹介した。

  1. プロファイラによる遅いメソッドの特定
  2. キャッシュによる無駄な処理の回避
  3. Lazy Instantiationによる処理の分散

 アプリケーションのチューニングで一番効果が覿面(てきめん)なのは、「何も処理させない」ことである。まずは、同じことを2度やっていないか、無駄なことをやっていないか、プロファイラを使えばすぐ分かるだろう。

チューニングはトレードオフ

 また繰り返すが、基本的にチューニングはトレードオフである。あるメリットを享受するために、デメリットを受ける可能性が高い。さらに、ソースコードに修正が及ぶため、再試験などの余計なコストも掛かってしまう。そのため、ソースコードレベルでのチューニングは最後の手段と考えた方がよいだろう。

 チューニングを行わなければならなくなったときは、チューニングが巻き起こすトレードオフを熟慮して行ってほしい。

@IT関連記事


コードから情報を追い出せ! プロパティファイルの常識
プログラマーの常識をJavaで身につける(9) 
もちろん、使ってますよね? ソースコードに設定情報をベタ書きすると、情報を書き換えるたびにコンパイルが必要ですしね
Java Solution」フォーラム 2007/11/29
Eclipse上でプロファイリングを実現する
連載:Eclipse徹底活用(6) コーディング作業とプロファイリングを繰り返しながらアプリケーションのチューニングができる。そんな便利なEclipseの活用法を紹介しよう
Java Solution」フォーラム 2003/10/31
プロファイラでメモリリークとパフォーマンス問題を解決
Java開発の問題解決を助ける(2) フリーで利用できるプロファイラ「NetBeans Profile」を使ってメモリリークとパフォーマンスの問題を解決する方法を紹介する
Java Solution」フォーラム 2005/8/10
事例に学ぶWebシステム開発のワンポイント
現場のエンジニアの経験から得られた、アプリケーション・サーバをベースとしたWebシステム開発におけるノウハウ、注意点について解説
第1回 クラスタ化すると遅くなる?
第2回 キャッシュが性能劣化をもたらす謎を解く
第3回 クラスタは何台までOK?
第4回 マルチスレッドのいたずらに注意
第5回 クラスタによるアプリケーションの動的アップデート
第6回 APサーバからの応答がなくなった、なぜ?
第7回 低負荷なのにCPU使用率が100%?

第8回 文字化け“???”の法則とその防止策
第9回 メモリは足りているのに“OutOfMemory”のなぞ
第10回 レスポンスキャッシュでパフォーマンス向上
第11回 JDBC接続を高速化−PreparedCacheの活用
第12回 ブラウザキャッシュでパフォーマンス向上
第13回 ファイルアップロード/ダウンロードに潜むわな
高負荷なのに片方のサーバにだけ余裕が……なぜ?
Linuxトラブルシューティング探偵団 第1回
 Linuxベースのシステムで起こるトラブルに、百戦錬磨の達人が立ち向かう! 実例を元に障害対応のプロセスを紹介します
Linux Square」フォーラム 2008/2/4

プロフィール
佐藤 聖規(さとう まさのり)

某大手SIerに勤務し、ソフトウェア開発の抜本的生産性向上のためEclipseを中心とした開発環境の整備に日夜いそしんでいる。
その傍ら、アーキテクトやトラブルシューターとしてプロジェクト支援も行っている。

1-2

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


Java Solution全記事一覧


TechTargetジャパン

Java Solution フォーラム 新着記事

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

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH