今回のトラブルの最大の原因は通信を行うごとに、値のまったく変わらないプロパティファイルにアクセスしてしまうことである。
そこで今回は、一度必要なプロパティの値をオブジェクト化したら、ロードしたプロパティをキャッシュ化しておき、2回目以降の通信時にはキャッシュから値を取得する形に変更することに決定した。
なお、このアプリケーションでは、プロパティファイルは更新されないため、キャッシュクリアや更新のためのキャッシュアルゴリズムは特に用いず、アプリケーションが終了するまでキャッシュを保持しておくこととした。
つまり、GOFのデザインパターンでいうところのシングルトンパターン(注意:シングルトンパターンの詳細な解説は「クラスのインスタンスを1つに保つ(Singletonパターン)」を参照してください)の適用を勧めた。
私はプロジェクトの開発者たちに修正のアドバイスをして現場を立ち去った。
なお、私たちのようなトラブルハッカーはプロジェクトのメンバーではないことが多い。そのためプロジェクトのアーキテクチャや業務に精通しているわけではない。
従って、問題点を解消するためのアドバイスだけで実際のソースコードの修正や再試験はプロジェクトに任せることがほとんどである。
問題特定から数日が経過して、私は問題が解決したか気になりながらも、平和な日々を過ごしていた。「便りがないのは元気な証拠」といわんばかりに問題が解決したプロジェクトからは連絡がないことが多い。
そう思っていた矢先、再びプロジェクトの担当者から電話がかかってきた。何でも、通信時のパフォーマンスは目標を達成したらしいが、それとは別の問題が発生したらしい。
とにかく電話では現状が伝わってこないため、再びプロジェクトへお邪魔してヒアリングを行うことにした。
プロジェクトは以前の分析結果に基づき、プロパティファイルのインスタンスをキャッシュ化した。しかし、また別の問題が発生してしまったらしい。
プロジェクトの担当者にヒアリングを行ったところ、以下の2点が判明した。
なお、ソースコードの修正は「プロパティインスタンスのキャッシュ化のみの修正」を行ったらしい。
上記の事実と現象から原因は、プロファイリングを行うまでもなく、容易に予想がついた。恐らく、起動時にプロパティファイルをキャッシュ化する処理を実施しているのだろう。
早速、担当者に確認したところ、やはり起動時にプロパティファイルのキャッシュ化を行っているらしい。さらに、以下の事実が判明した。
上記の処理を起動時にすべて行ってしまっては、アプリケーションの起動が著しく遅くなってしまうのは無理もない。まさしく、「過ぎたるは及ばざるがごとし」である。
ここで1つの疑問が浮かんだ。「なぜ、起動時にすべてのプロパティファイルをキャッシュ化したのか」である。
この理由は、サーバ側のパフォーマンスに問題がなかったのは、起動時に必要なプロパティファイルをすべてインスタンス化して再利用していたからであり、その仕組みを踏襲したとのことである。
起動時にすべてのプロパティをキャッシュ化する方式は、一度起動すればメンテナンスのとき以外は再起動をしないサーバ型のアプリケーションでは有効な手段だといえる。
ただし、今回は必要なときだけ起動して、不必要になればアプリケーションを終了するクライアント側で動くリッチアプリケーション型のアプリケーションである。起動が著しく遅くては、ユーザーへ与えるストレスが大きくなってしまう。
そこで、プロパティファイルをインスタンス化するのは、初めてプロパティの値が使われるタイミングとした。すなわち「Lazy Instantiation(怠惰なインスタンス化)」である。
つまり、起動時は「何もしない」というチューニングを施すこととなる。
なお、この起動時にすべてのインスタンス化を行うような手法を「Eager Instantiation(意欲的なインスタンス化)」といい、起動時間にさほど気を使わず、比較的簡単にメモリを増設可能なサーバ型のアプリケーションでは有効な手法といえる。
これにより、初めてプロパティの値が利用されるときは処理が遅くなってしまうが、起動時の著しいパフォーマンスの低下は抑えられる。
すべてのプログラムを修正すれば、抜本的な対策を行えるかもしれないが、もちろんそんなことをやっている時間はない。このように、チューニングは往々にしてトレードオフである。
そしてLazy Instantiationを行うことで、ようやくプロジェクトは目標のパフォーマンスを達成できた……。
今回についてまとめると、以下の3つのテクニックでチューニングを行うトラブルハックを紹介した。
アプリケーションのチューニングで一番効果が覿面(てきめん)なのは、「何も処理させない」ことである。まずは、同じことを2度やっていないか、無駄なことをやっていないか、プロファイラを使えばすぐ分かるだろう。
また繰り返すが、基本的にチューニングはトレードオフである。あるメリットを享受するために、デメリットを受ける可能性が高い。さらに、ソースコードに修正が及ぶため、再試験などの余計なコストも掛かってしまう。そのため、ソースコードレベルでのチューニングは最後の手段と考えた方がよいだろう。
チューニングを行わなければならなくなったときは、チューニングが巻き起こすトレードオフを熟慮して行ってほしい。
Copyright © ITmedia, Inc. All Rights Reserved.