アプリ開発でも、よ〜く考えよう。キャッシュは大事だよ:現場から学ぶWebアプリ開発のトラブルハック(12)(2/2 ページ)
本連載は、現場でのエンジニアの経験から得られた、APサーバをベースとしたWebアプリ開発における注意点やノウハウについて解説するハック集である。現在起きているトラブルの解決や、今後の開発の参考として大いに活用していただきたい。(編集部)
キャッシュは、ためるものではなく使うもの
今回のトラブルの最大の原因は通信を行うごとに、値のまったく変わらないプロパティファイルにアクセスしてしまうことである。
そこで今回は、一度必要なプロパティの値をオブジェクト化したら、ロードしたプロパティをキャッシュ化しておき、2回目以降の通信時にはキャッシュから値を取得する形に変更することに決定した。
なお、このアプリケーションでは、プロパティファイルは更新されないため、キャッシュクリアや更新のためのキャッシュアルゴリズムは特に用いず、アプリケーションが終了するまでキャッシュを保持しておくこととした。
つまり、GOFのデザインパターンでいうところのシングルトンパターン(注意:シングルトンパターンの詳細な解説は「クラスのインスタンスを1つに保つ(Singletonパターン)」を参照してください)の適用を勧めた。
私はプロジェクトの開発者たちに修正のアドバイスをして現場を立ち去った。
■トラブルハッカーはアドバイスがほとんど
なお、私たちのようなトラブルハッカーはプロジェクトのメンバーではないことが多い。そのためプロジェクトのアーキテクチャや業務に精通しているわけではない。
従って、問題点を解消するためのアドバイスだけで実際のソースコードの修正や再試験はプロジェクトに任せることがほとんどである。
■ところが、問題再発!?
問題特定から数日が経過して、私は問題が解決したか気になりながらも、平和な日々を過ごしていた。「便りがないのは元気な証拠」といわんばかりに問題が解決したプロジェクトからは連絡がないことが多い。
そう思っていた矢先、再びプロジェクトの担当者から電話がかかってきた。何でも、通信時のパフォーマンスは目標を達成したらしいが、それとは別の問題が発生したらしい。
とにかく電話では現状が伝わってこないため、再びプロジェクトへお邪魔してヒアリングを行うことにした。
過ぎたるは及ばざるがごとし
プロジェクトは以前の分析結果に基づき、プロパティファイルのインスタンスをキャッシュ化した。しかし、また別の問題が発生してしまったらしい。
■再発した2つの問題
プロジェクトの担当者にヒアリングを行ったところ、以下の2点が判明した。
- 通信時のパフォーマンスは目標を達成した
- アプリケーションの起動が著しく遅くなってしまった
なお、ソースコードの修正は「プロパティインスタンスのキャッシュ化のみの修正」を行ったらしい。
上記の事実と現象から原因は、プロファイリングを行うまでもなく、容易に予想がついた。恐らく、起動時にプロパティファイルをキャッシュ化する処理を実施しているのだろう。
■起動時のプロパティファイルのキャッシュ化に加え……
早速、担当者に確認したところ、やはり起動時にプロパティファイルのキャッシュ化を行っているらしい。さらに、以下の事実が判明した。
- プロパティファイルは業務種別ごとに分かれており、全部で10個以上ある
- 1つのプロパティファイルは数メガバイトから数十メガバイトの大きなサイズである
上記の処理を起動時にすべて行ってしまっては、アプリケーションの起動が著しく遅くなってしまうのは無理もない。まさしく、「過ぎたるは及ばざるがごとし」である。
■なぜ起動時に?
ここで1つの疑問が浮かんだ。「なぜ、起動時にすべてのプロパティファイルをキャッシュ化したのか」である。
この理由は、サーバ側のパフォーマンスに問題がなかったのは、起動時に必要なプロパティファイルをすべてインスタンス化して再利用していたからであり、その仕組みを踏襲したとのことである。
怠惰(Lazy)に問題を解消
起動時にすべてのプロパティをキャッシュ化する方式は、一度起動すればメンテナンスのとき以外は再起動をしないサーバ型のアプリケーションでは有効な手段だといえる。
ただし、今回は必要なときだけ起動して、不必要になればアプリケーションを終了するクライアント側で動くリッチアプリケーション型のアプリケーションである。起動が著しく遅くては、ユーザーへ与えるストレスが大きくなってしまう。
そこで、プロパティファイルをインスタンス化するのは、初めてプロパティの値が使われるタイミングとした。すなわち「Lazy Instantiation(怠惰なインスタンス化)」である。
つまり、起動時は「何もしない」というチューニングを施すこととなる。
■意欲的なインスタンス化もある
なお、この起動時にすべてのインスタンス化を行うような手法を「Eager Instantiation(意欲的なインスタンス化)」といい、起動時間にさほど気を使わず、比較的簡単にメモリを増設可能なサーバ型のアプリケーションでは有効な手法といえる。
これにより、初めてプロパティの値が利用されるときは処理が遅くなってしまうが、起動時の著しいパフォーマンスの低下は抑えられる。
すべてのプログラムを修正すれば、抜本的な対策を行えるかもしれないが、もちろんそんなことをやっている時間はない。このように、チューニングは往々にしてトレードオフである。
そしてLazy Instantiationを行うことで、ようやくプロジェクトは目標のパフォーマンスを達成できた……。
ご利用は計画的に
今回についてまとめると、以下の3つのテクニックでチューニングを行うトラブルハックを紹介した。
- プロファイラによる遅いメソッドの特定
- キャッシュによる無駄な処理の回避
- Lazy Instantiationによる処理の分散
アプリケーションのチューニングで一番効果が覿面(てきめん)なのは、「何も処理させない」ことである。まずは、同じことを2度やっていないか、無駄なことをやっていないか、プロファイラを使えばすぐ分かるだろう。
■チューニングはトレードオフ
また繰り返すが、基本的にチューニングはトレードオフである。あるメリットを享受するために、デメリットを受ける可能性が高い。さらに、ソースコードに修正が及ぶため、再試験などの余計なコストも掛かってしまう。そのため、ソースコードレベルでのチューニングは最後の手段と考えた方がよいだろう。
チューニングを行わなければならなくなったときは、チューニングが巻き起こすトレードオフを熟慮して行ってほしい。
- 数百キロのコードでブルー - ドクターTomcat緊急救命
- DB操作の“壁”を壊すJPAが起こした「赤壁の戦い」
- アプリ開発でも、よ〜く考えよう。キャッシュは大事だよ
- スレッドダンプの森で覚えた死のロックへの違和感
- ThreadとHashMapに潜む無限回廊は実に面白い?
- JavaのGC頻度に惑わされた年末年始の苦いメモリ
- 肥え続けるTomcatと胃を痛めるトラブルハッカー
- 【トラブル大捜査線】失われたコネクションを追え!
- 【真夏の夜のミステリー】Tomcatを殺したのは誰だ?
- OutOfMemoryエラー発生!? GCがあるのに、なぜ?
- DBアクセスのトラブルは終盤で発覚しがち……
- 【実録ドキュメント】そのログ本当に必要ですか?
- “Stop the World”を防ぐコンカレントGCとは?
- Webアプリの問題点を「見える化」する7つ道具
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Javaプログラムからプロパティファイルを参照する
- Eclipseでプロパティファイルを編集する
- コードから情報を追い出せ! プロパティファイルの常識
プログラマーの常識をJavaで身につける(9) もちろん、使ってますよね? ソースコードに設定情報をベタ書きすると、情報を書き換えるたびにコンパイルが必要ですしね - Eclipse上でプロファイリングを実現する
連載:Eclipse徹底活用(6) コーディング作業とプロファイリングを繰り返しながらアプリケーションのチューニングができる。そんな便利なEclipseの活用法を紹介しよう - プロファイラでメモリリークとパフォーマンス問題を解決
Java開発の問題解決を助ける(2) フリーで利用できるプロファイラ「NetBeans Profile」を使ってメモリリークとパフォーマンスの問題を解決する方法を紹介する - 事例に学ぶ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ベースのシステムで起こるトラブルに、百戦錬磨の達人が立ち向かう! 実例を元に障害対応のプロセスを紹介します