PHPで簡単キャッシュ高速化

※以前別の場所で書いた文章を備忘的に書き記しておきます。

【投稿年月日】2012-04-20 【ジャンル】PHP/MySQL

 手軽にPHPの表示スピードを2倍以上(当社比)にする方法。

 元ネタは下記ページ。

PHP 特別なライブラリなしで簡単に使える簡易キャッシュ
h19e.jugem.jp/?eid=34

 これを、ユーザー定義関数ごとにキャッシュできるようにしてみた。なお、キャッシュファイルを格納するために、書き込み権限のあるディレクトリを、事前に作成しておく必要がある。

簡単キャッシュ: getCacheFile()関数

 function getCacheFile($idFunc="", $cacheTime=120) {
  $cacheFile = "./tmp/".$idFunc; // キャッシュファイルの場所
  if(!function_exists($idFunc)) {
   return;
  }
  if(file_exists($cacheFile)) {
   $time = filemtime($cacheFile);
   if(($time + $cacheTime)>time()) {
    return unserialize(file_get_contents($cacheFile));
   }
  }
  $body = call_user_func($idFunc);
  $file = new SplFileObject($cacheFile, "w"); // PHP5以上
  $file->fwrite(serialize($body));
  return $body;
 }

getCacheFile()関数の使用例

 使用例は以下の通り。
 echo getCacheFile("heavyProcessingFunction"); // キャッシュしたいユーザー定義関数名を第1引数に指定

 function heavyProcessingFunction() {
  $text = "";
 /*
 MySQLなどを使った重い処理を実行
 */
  return $text; // 文字列を返す
 }
 キャッシュする時間を指定したければ以下のように記述。秒単位なので、1分は「60」、1時間は「3600」。
 echo getCacheFile("heavyProcessingFunction", 3600); // キャッシュする時間を第2引数に指定

 function heavyProcessingFunction() {
  $text = "";
 /*
 MySQLなどを使った重い処理を実行
 */
  return $text; // 文字列を返す
 }
 文字列だけでなく配列のキャッシュにも対応。
 $arys = getCacheFile("heavyProcessingFunctionAry"); // キャッシュしたいユーザー定義関数名を第1引数に指定
 echo $arys[0]." / ".$arys[1];

 function heavyProcessingFunctionAry() {
  $text = array("","");
 /*
 MySQLなどを使った重い処理を実行
 */
  return array($text[0], $text[1]); // 配列を返す
 }

簡単キャッシュ: getCacheFile()関数 (*クラス対応版)

 クラスで使う場合は以下のような感じで書き換え。
 function getCacheFile($idFunc="", $cacheTime=120, $idClass="MAIN") { // クラス名を第3引数で指定
  $cacheFile = "./tmp/".$idFunc; // キャッシュファイルの場所
  if(!method_exists($idClass, $idFunc)) {
   return;
  }
  if(file_exists($cacheFile)) {
   $time = filemtime($cacheFile);
   if(($time + $cacheTime)>time()) {
    return unserialize(file_get_contents($cacheFile));
   }
  }
  $body = call_user_func(array($idClass, $idFunc));
  $file = new SplFileObject($cacheFile, "w"); // PHP5以上
  $file->fwrite(serialize($body));
  return $body;
 }

getCacheFile()関数を実際に使ってみて

 「EDIUNET」で使い始めているが、トップページの表示が2倍以上速くなった。ページによっては5倍以上速くなっている。
 例えば、売上高等の勘定科目一覧をMySQLテーブルから毎回呼び出していたが、これをキャッシュに変更。勘定科目なんて、ほとんど変化がないから、更新頻度は1日1回で十分。日によってページビューが違うので正確には分からないが、MySQLの呼び出し数が激減したことは確か。

getCacheFile()関数の特徴

 getCacheFile()関数の最大の特徴は、指定した関数が丸ごとキャッシュされること。よって、既存コードの修正がほとんど必要ないので導入が楽。例えば、
 echo heavyProcessingFunction();
ならば、
 echo getCacheFile("heavyProcessingFunction");
に書き換えるだけでOK。

 また、getCacheFile()関数において「serialize」と「unserialize」を使っているので、文字列だけでなく配列をキャッシュとして扱うことが可能。これが地味に便利。

getCacheFile()関数の使い方

 例えば、以下のような基準を設けて、関数(パーツ)ごとにキャッシュする時間を微調整して使う。
  1. 更新頻度が非常に高く、リアルタイム表示が必要なもの → getCacheFile()関数を使わない
  2. 更新頻度が高いもの → キャッシュする時間を「60」に設定(*1分)
  3. 更新頻度は低いが、変更された場合の影響が甚大なもの → キャッシュする時間を「3600」に設定(*1時間)
  4. 更新がほとんどないもの → キャッシュする時間を「86400」に設定(*1日)
 プログラムを更新した場合など、キャッシュをオールクリアしたいときは、キャッシュファイルを格納するディレクト内のファイルを、FTPなどで一括削除すればOK。

getCacheFile()関数の注意点

 echo getCacheFile("heavyProcessingFunctionPlus_menu_2"); // 間にかませる関数名を第1引数に指定
 function heavyProcessingFunctionPlus_menu_2() { // 間にかませる関数
  return heavyProcessingFunctionPlus("menu", 2);
 }
 function heavyProcessingFunctionPlus($str1, $str2) { // キャッシュしたい関数
  $text = "";
 /*
 MySQLなどを使った重い処理を実行
 */
  return $text;
 }

EDIUNET | PHP/MySQL | 独り言 | 提供サービス | JavaScript