gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

キャッシュに関する考察

んと。元ネタは、ちと現在やり取りがある先の一つから「Smartyと同等のキャッシュ機能をMWのconvにも欲しいんだけど」というお話。
キャッシュについては過去にいろ〜いろと検証想定実装しくじりをしたので(苦笑)、考察&メモ。


まず「キャッシュってなに?」。
面倒なのであちこちからちと引用。

使用頻度の高いデータを高速な記憶装置に蓄えておくことにより、いちいち低速な装置から読み出す無駄を省いて高速化すること。また、その際に使われる高速な記憶装置。
例えば、メモリはハードディスクに比べれば何百倍も高速にデータの読み書きが行えるため、使用頻度の高いデータをメモリ内に保持しておくことにより、すべてのデータをハードディスクに置いた場合よりも処理を高速化することができる。この場合、メモリがハードディスクのキャッシュである。

元々の単語の意味は、

  名詞:食料などの隠し場所、貯蔵庫。

  動詞:食料などを貯えておく、隠しておく。

 そこから、コンピュータ用語としては…

 キャッシュメモリの略。

 CPUの処理速度が向上するにつれて、メインメモリからのデータ転送速度の遅さが全体の処理速度向上の足を引っ張るようになった。

 そこでメインメモリよりさらに高速にデータのやりとりをできるメモリを置き、ここに頻繁に使われるデータを一時的に置くようになった。

キャッシュ (en:cache) は、CPUのバスやネットワークなど様々な情報伝達経路において、ある領域から他の領域へ情報を転送する際、その転送遅延を極力隠蔽化させ転送効率を向上させるために考案された記憶階層の実現手段である。実装するシステムに応じてハードウエア/ソフトウエア双方の形態がある(今後コンピュータのプログラムなども含め全ての転送すべき情報をデータと表す)。

要約すると「データ溜めとこうや便利だから」って話。


では質問。
「置換エンジンにおける"溜めたいデータ"ってなに?」
もうちょっと具体的に。
「置換前のテンプレートデータを溜めたいの? 置換された出力結果データを溜めたいの?」
ここでいつもの発言を一つ。「便利な単語は使わない」。きちんと「どんなデータをどんな目的で溜めたいのか」を、明示するように意識しましょう。


んで。要望としては「Smartyのキャッシュ」だったので、調査。
とりあえず http://sunset.freespace.jp/Smarty/SmartyManual_2-6-5J_html/caching.html この辺参照。
…困ったことに「置換された出力結果のキャッシュ」であることが判明。
なぜ困るのか?


「置換前のテンプレートデータを溜めたい」ってのは、サイトによってはままありえまして。
具体的には「テンプレート情報の総量が案外に少ない」「何らかの形で、メモリ上に情報が保持しておける(Fast CGIとか便利ですねぇ)」「アクセス数が案外に半端じゃない」なんてぇときに、重宝します。
この場合、「HDDから読み出すべき情報をメモリに格納することによってアクセス速度全体を持ち上げる」ってのが一番のねらい目です。
テンプレートを更新したときに、メモリ上の情報を消すなどの処理が必要ではありますが、まぁ便利です。
難点はそのまんま「メモリ食いがでかいこと」。気をつけないと、かな〜りたっぷりお召し上がられます。


「置換後の出力情報を溜めたい」ってのは………ええあるにはあるんですよく。
ただ、この部分は限りなく注意しないと危険がいっぱいです。
期待されている部分ってのは割合に明白で、概ね「処理しないで出力することによるCPU負荷メモリ負荷の軽減」「DBなどへのアクセスの軽減」ってあたりがメイン。つまり「何らかのリソースの負荷軽減」ってのが根底にあります。
さて問題が一つ。PHPで出力するからには、通常大抵が「動的なPage」です(ので、静的Pageを出力してる場合以下のすべての前提が覆ります…レアだとは思いますが)。
んで。動的なPageってのは大抵「コロコロと変わるから」こその「動的なPage」になります。


例えば。掲示板とかの、ある程度「みんなで見倒す」ようなモノの場合。………一応ある程度までは効果があります。書き込みが入った瞬間にキャッシュクリアすればいいので。
ただ、それやるなら、置換エンジンじゃなくて、そもプログラムの開始時に「キャッシュ判定する」とか、「そもPHP動かさずに閲覧させる」とか、設計部分でヘッジしたほうが効率は高いです。


で…もしそれ以外の部分で。具体的には、例えば「ユーザ入力周り」とか「ECサイト系で買い物籠関連」とか「商品だの特定情報だのをパラメタ"id"とかで指定するもの」とかの場合。
キャッシュは意味を成さない…というよりももうちょっと積極的に「害を成す」ものになります。


単純にキャッシュした場合。非常にクラッカーフレンドリーな設計になります。具体的には、例えばキャッシュ時間が10分の場合。「あるユーザが入力すると、10分間は誰でもそのユーザの入力が閲覧できる」状態になります。個人情報丸裸です。
例えばSmartyの場合。「キャッシュID」というもので区別が出来るようになります。
もしこれに「セッションID」を用いた場合。「1ユーザごとにキャッシュファイルが作成される」のでHDDが圧迫されますが、一方で「そのユーザが指定時間以内にもう一度同じpageを見ない限り」キャッシュファイルはただの「HDDの肥やし」です。
しかもセッションIDは通常(セキュリティを考えると)10分とか15分とかで振りなおすので、そういった点でも「キャッシュの意味」が薄れます。
商品の出力Pageとかで、商品IDをキャッシュIDにした場合。商品の数だけキャッシュファイルが出来上がります。…まぁこっちはまだ多少意味がありそうですが。
でも、それならそれでやっぱり「設計きちんとして、処理の一番手前でキャッシュ使える」ようにしないと、あんまり旨みがありません。


かくして「困った」事になります。
使っちゃまずいシーンが山盛りな上に、有効なシーンなら「Smarty(っつか置換エンジン)にキャッシュ機能持たせるよりも、設計的にとか処理的にもっと手前できちんとキャッシュ判定したほうが圧倒的によい」状況になるので。


…いつも思うのですが。なんでこう「置換エンジン」とは無関係な機能が多いんでしょう(苦笑
せめて。せめて「違うクラスで実装してoptionでくっつけられる」とかなら、もうちょっと便利だと思うのですが。


んで。いつもの台詞でしめてみませう。「便利な言葉は使わない」。
キャッシュという甘い言葉は、その意味とメリットとデメリットをきちんと深く考察しておきましょう。
いやまぁ「きちんと考察した上で」「有効に使う」なら、非常に重要な概念なので。