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;
}
$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」。function heavyProcessingFunction() {
$text = "";
/*
MySQLなどを使った重い処理を実行
*/
return $text; // 文字列を返す
}
echo getCacheFile("heavyProcessingFunction", 3600); // キャッシュする時間を第2引数に指定
function heavyProcessingFunction() {
$text = "";
/*
MySQLなどを使った重い処理を実行
*/
return $text; // 文字列を返す
}
文字列だけでなく配列のキャッシュにも対応。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]); // 配列を返す
}
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;
}
$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()関数の使い方
例えば、以下のような基準を設けて、関数(パーツ)ごとにキャッシュする時間を微調整して使う。- 更新頻度が非常に高く、リアルタイム表示が必要なもの → getCacheFile()関数を使わない
- 更新頻度が高いもの → キャッシュする時間を「60」に設定(*1分)
- 更新頻度は低いが、変更された場合の影響が甚大なもの → キャッシュする時間を「3600」に設定(*1時間)
- 更新がほとんどないもの → キャッシュする時間を「86400」に設定(*1日)
getCacheFile()関数の注意点
- キャッシュファイルを格納するディレクトのパスについては、相対パスではなく絶対パスを使った方がいい場合もある。
- PHP4の場合、SplFileObject()が使えないのでfile()関数等で代用する必要がある。
- 同一ページにおいて、モバイル端末向けページや英語ページなどがある場合、別にキャッシュを用意するか、キャッシュを使わないなどの工夫が必要になる。
- 引数が必要な関数をキャッシュする場合は、関数をもう一つかませる。(※call_user_func() に引数を指定すると挙動が怪しくなるため)
echo getCacheFile("heavyProcessingFunctionPlus_menu_2"); // 間にかませる関数名を第1引数に指定
function heavyProcessingFunctionPlus_menu_2() { // 間にかませる関数
return heavyProcessingFunctionPlus("menu", 2);
}
function heavyProcessingFunctionPlus($str1, $str2) { // キャッシュしたい関数
$text = "";
/*
MySQLなどを使った重い処理を実行
*/
return $text;
}
function heavyProcessingFunctionPlus_menu_2() { // 間にかませる関数
return heavyProcessingFunctionPlus("menu", 2);
}
function heavyProcessingFunctionPlus($str1, $str2) { // キャッシュしたい関数
$text = "";
/*
MySQLなどを使った重い処理を実行
*/
return $text;
}
EDIUNET | PHP/MySQL | 独り言 | 提供サービス | JavaScript