現場から学ぶWebアプリ開発のトラブルハック 第12回
アプリ開発でも、よ〜く考えよう。
キャッシュは大事だよ
佐藤聖規
2008/10/15
キャッシュは、ためるものではなく使うもの
今回のトラブルの最大の原因は通信を行うごとに、値のまったく変わらないプロパティファイルにアクセスしてしまうことである。
そこで今回は、一度必要なプロパティの値をオブジェクト化したら、ロードしたプロパティをキャッシュ化しておき、2回目以降の通信時にはキャッシュから値を取得する形に変更することに決定した。
![]() |
| 図4 キャッシュ化した後の通信時の挙動 |
なお、このアプリケーションでは、プロパティファイルは更新されないため、キャッシュクリアや更新のためのキャッシュアルゴリズムは特に用いず、アプリケーションが終了するまでキャッシュを保持しておくこととした。
つまり、GOFのデザインパターンでいうところのシングルトンパターン(注意:シングルトンパターンの詳細な解説は「クラスのインスタンスを1つに保つ(Singletonパターン)」を参照してください)の適用を勧めた。
私はプロジェクトの開発者たちにに修正のアドバイスをして現場を立ち去った。
■ トラブルハッカーはアドバイスがほとんど
なお、私たちのようなトラブルハッカーはプロジェクトのメンバーではないことが多い。そのためプロジェクトのアーキテクチャや業務に精通しているわけではない。
従って、問題点を解消するためのアドバイスだけで実際のソースコードの修正や再試験はプロジェクトに任せることがほとんどである。
■ ところが、問題再発!?
問題特定から数日が経過して、私は問題が解決したか気になりながらも、平和な日々を過ごしていた。「便りがないのは元気な証拠」といわんばかりに問題が解決したプロジェクトからは連絡がないことが多い。
そう思っていた矢先、再びプロジェクトの担当者から電話がかかってきた。何でも、通信時のパフォーマンスは目標を達成したらしいが、それとは別の問題が発生したらしい。
とにかく電話では現状が伝わってこないため、再びプロジェクトへお邪魔してヒアリングを行うことにした。
過ぎたるは及ばざるがごとし
プロジェクトは以前の分析結果に基づき、プロパティファイルのインスタンスをキャッシュ化した。しかし、また別の問題が発生してしまったらしい。
■ 再発した2つの問題
プロジェクトの担当者にヒアリングを行ったところ、以下の2点が判明した。
- 通信時のパフォーマンスは目標を達成した
- アプリケーションの起動が著しく遅くなってしまった
なお、ソースコードの修正は「プロパティインスタンスのキャッシュ化のみの修正」を行ったらしい。
上記の事実と現象から原因は、プロファイリングを行うまでもなく、容易に予想がついた。恐らく、起動時にプロパティファイルをキャッシュ化する処理を実施しているのだろう。
■ 起動時のプロパティファイルのキャッシュ化に加え……
早速、担当者に確認したところ、やはり起動時にプロパティファイルのキャッシュ化を行っているらしい。さらに、以下の事実が判明した。
- プロパティファイルは業務種別ごとに分かれており、全部で10個以上ある
- 1つのプロパティファイルは数メガバイトから数十メガバイトの大きなサイズである
![]() |
| 図5 起動時にすべてのプロパティをキャッシュ化する方式 |
上記の処理を起動時にすべて行ってしまっては、アプリケーションの起動が著しく遅くなってしまうのは無理もない。まさしく、「過ぎたるは及ばざるがごとし」である。
■ なぜ起動時に?
ここで1つの疑問が浮かんだ。「なぜ、起動時にすべてのプロパティファイルをキャッシュ化したのか」である。
この理由は、サーバ側のパフォーマンスに問題がなかったのは、起動時に必要なプロパティファイルをすべてインスタンス化して再利用していたからであり、その仕組みを踏襲したとのことである。
怠惰(Lazy)に問題を解消
起動時にすべてのプロパティをキャッシュ化する方式は、一度起動すればメンテナンスのとき以外は再起動をしないサーバ型のアプリケーションでは有効な手段だといえる。
ただし、今回は必要なときだけ起動して、不必要になればアプリケーションを終了するクライアント側で動くリッチアプリケーション型のアプリケーションである。起動が著しく遅くては、ユーザーへ与えるストレスが大きくなってしまう。
そこで、プロパティファイルをインスタンス化するのは、初めてプロパティの値が使われるタイミングとした。すなわち「Lazy Instantiation(怠惰なインスタンス化)」である。
![]() |
| 図6 Lazy Instantiationによるキャッシュ化 |
つまり、起動時は「何もしない」というチューニングを施すこととなる。
■ 意欲的なインスタンス化もある
なお、この起動時にすべてのインスタンス化を行うような手法を「Eager Instantiation(意欲的なインスタンス化)」といい、起動時間にさほど気を使わず、比較的簡単にメモリを増設可能なサーバ型のアプリケーションでは有効な手法といえる。
これにより、初めてプロパティの値が利用されるときは処理が遅くなってしまうが、起動時の著しいパフォーマンスの低下は抑えられる。
すべてのプログラムを修正すれば、抜本的な対策を行えるかもしれないが、もちろんそんなことをやっている時間はない。このように、チューニングは往々にしてトレードオフである。
そしてLazy Instantiationを行うことで、ようやくプロジェクトは目標のパフォーマンスを達成できた……。
ご利用は計画的に
今回についてまとめると、以下の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 |
||
| 高負荷なのに片方のサーバにだけ余裕が……なぜ? Linuxトラブルシューティング探偵団 第1回 Linuxベースのシステムで起こるトラブルに、百戦錬磨の達人が立ち向かう! 実例を元に障害対応のプロセスを紹介します 「Linux Square」フォーラム 2008/2/4
|
||
| プロフィール |
佐藤 聖規(さとう まさのり) 某大手SIerに勤務し、ソフトウェア開発の抜本的生産性向上のためEclipseを中心とした開発環境の整備に日夜いそしんでいる。その傍ら、アーキテクトやトラブルシューターとしてプロジェクト支援も行っている。 |
1-2 |
| Index | |
| 第12回 アプリ開発でも、よ〜く考えよう。キャッシュは大事だよ | |
| Page1 無駄”より“遅い”ものはない 先入観は判断を鈍らせる |
|
| Page2 キャッシュは、ためるものではなく使うもの 過ぎたるは及ばざるがごとし 怠惰(Lazy)に問題を解消 ご利用は計画的に |
|
現場から学ぶWebアプリ開発のトラブルハック バックナンバー 連載インデックスへ»
- 第1回 Webアプリの問題点を「見える化」する7つ道具
- 第2回 “Stop the World”を防ぐコンカレントGCとは?
- 第3回 【実録ドキュメント】そのログ本当に必要ですか?
- 第4回 DBアクセスのトラブルは終盤で発覚しがち……
- 第5回 OutOfMemoryエラー発生!? GCがあるのに、なぜ?
- 第6回 【真夏の夜のミステリー】Tomcatを殺したのは誰だ?
- 第7回 【トラブル大捜査線】失われたコネクションを追え!
- 第8回 肥え続けるTomcatと胃を痛めるトラブルハッカー
- 第9回 JavaのGC頻度に惑わされた年末年始の苦いメモリ
- 第10回 ThreadとHashMapに潜む無限回廊は実に面白い?
- 第11回 スレッドダンプの森で覚えた死のロックへの違和感
- 第12回 アプリ開発でも、よ〜く考えよう。キャッシュは大事だよ
- 第13回 DB操作の“壁”を壊すJPAが起こした「赤壁の戦い」
- 第14回 数百キロのコードでブルー - ドクターTomcat緊急救命
| Java Solution全記事一覧 |
TechTargetジャパン
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承 (2012/5/22)
インポート、パッケージオブジェクト、抽象クラス/抽象メソッド、オーバーライド、final、シールドクラスなども - 基幹系システムでCloud SQLは使えるか試してみた (2012/5/17)
サンプルとしてMRPシステムを作成して動かし、「再帰呼び出し」などのパフォーマンスを測定して検証してみます - アジャイル管理ツール9選+Pivotal Tracker入門 (2012/5/14)
群雄割拠のアジャイルプロジェクト管理ツールを9つ紹介し、特に注目を集めているPivotal Trackerの基本的な使い方を解説します - サーバサイドJSやJavaでWebアプリが作れるXPages (2012/5/11)
Notes/Dominoの資産をサーバサイドJavaScriptやJavaで操作し、HTMLやJavaScript、CSSをUIにできる技術を紹介
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -




某大手SIerに勤務し、ソフトウェア開発の抜本的生産性向上のためEclipseを中心とした開発環境の整備に日夜いそしんでいる。