cakephperの日記(CakePHP, Laravel, PHP)


継続的WebセキュリティテストサービスVAddyを始めました!

2009-10-07

CakePHPのキャッシュ時間をコントロールする

CakePHP1.2.5を使ってます。

特に情報が一定期間変わらないのにDBアクセスが走るページが、TOPページだったり、アクセスが多いページだった場合、キャッシュはパフォーマンス改善に抜群の効果があります。

Cakeキャッシュを使うと、app/tmp/cache以下にキャッシュファイルを作って、それを参照してDBアクセスを回避するなんてことが簡単にできます。CakeキャッシュAPCを使ってメモリ上に載せるとかも簡単です。

今回は、複数ポイントで、異なるキャッシュ時間を持たせたいときのTips

core.phpキャッシュを使う定義(デフォルトのまま)

Cache::config('default', array('engine' => 'File'));

ここの定義を、FileからApcにすればメモリに載せたりできます。


あるコントローラで、モデルを使ってDBから読み込んだ結果(配列データ)を60秒キャッシュする場合

<?php

class PostController extends AppController {

  var $uses = array('Post');

  function index() {

    $return_data = null;
    Cache::set(array('duration' => '+60 seconds'));
    if( ($return_data = Cache::read('PostController-index') ) === false ){

      $return_data = $this->Post->find('all');
      Cache::set(array('duration' => '+60 seconds'));
      Cache::write('PostController-index' , $return_data);
    }

    $this->set('data',$return_data);
  }
}

こうすると1回目のアクセスでDBからデータを取得し、その結果の配列データを、app/tmp/cache/PostController-indexというファイルにシリアライズして出力します。60秒以内にアクセスすればキャッシュデータがあるので、キャッシュファイルの内容を、$return_dataに入れます。

基本はこれだけです。超簡単、便利! 注意点は、Cache::readの前と、Cache::writeの前に、それぞれCache::setでキャッシュ時間をセットする必要があることです。これをしないとデフォルトの値がキャッシュ時間にセットされてしまいます。

参照: http://book.cakephp.org/ja/view/773/Cache-set

CakeCacheは、コントローラじゃなくても、モデルでもどこでも使えますし、配列データでも何でも突っ込めるので、とても便利です。 他の場所で、1時間のキャッシュを使う場合は、

      Cache::set(array('duration' => '+3600 seconds'));
      Cache::write('HogeModel-getData' , $return_data);

こうすればOK。注意点は、キャッシュファイル名が重複しないようにすること。例えばモデル/コントローラ名-メソッド名-パラメータみたいな。

durationの指定は、秒じゃなくても、+1 dayとか、+2 hoursとかでもいけます


余談ですが、Cache::read,writeメソッドには、引数でconfigの値をセットできます。

http://book.cakephp.org/ja/view/766/Cache-read

http://book.cakephp.org/ja/view/767/Cache-write

これを使うと、core.php

Cache::config('default', array('engine' => 'File'));
Cache::config('onemin', array('engine' => 'File','duration'=> 60,));
Cache::config('onehour', array('engine' => 'File','duration'=> 3600,));

として、複数定義をしておけば、Cache::read,write時にそれを指定するだけでいけます。

Cache::read('PostController-index', 'onemin')
Cache::write('PostController-index' , $return_data,'onemin');

追記:

英語ブログの方で同じ記事を投稿したら、コメントがありました。

http://cake.eizoku.com/blog/?p=93#comments

キャッシュのファイル名の重複を避けたかったら、findのパラメータ配列をserializeしてmd5にかけて、それをつけると良いよというもの。キャッシュファイル名は、

PostController-index-9e107d9d372bb6826bd81d3542a419d6

こんな感じになる。

コメントくれた二人は、CakeFestに来てた人。

2009-01-01

Cakephp1.2finalとrc3のパフォーマンス比較 on MacOS X

前回のXAMPP on WindowsXPのパフォーマンス比較で、静的htmlのアクセスでも性能が9req/secしか出なかったので、XAMPPApacheもしくはWindows上で動かすabコマンドに原因があるのかなと思ったので、手元にあったMac OSXで試してみました

APCやZend Optimizerは有効にしていなく、CakeのDebugは0で行っています。abコマンドを使ってlocalhostApacheに接続してパフォーマンス計測しました。


今回は、下記の同時接続50、総アクセス数200という設定でabコマンドでテスト

ab -c 50 -n 200 http://localhost


まず、静的なhtmlは、3000req/secほど出ました。

helloworldを表示するような単純なphpは2000req/secぐらい出ました。


続いて、modelを使わずに単純にhelloworldと書いたviewファイルのみを表示するCakePHPを比較

CakePHP1.2 RC3
 34req/sec

CakePHP1.2 final
 34req/sec

特に差はありません。APCインストールすればもっと性能があがるはずです。


最後に、blogを3件表示するだけのもの

CakePHP1.2 RC3
 22req/sec

CakePHP1.2 final
 22req/sec

特に差はないですね。

MacAPCダウンロードしてMakeしてシェアードオブジェクトファイルにして、php.iniのextensionで読み込むようにしてテストしようとしたけど、Apacheを起動したらApacheエラーログに下記のエラーが出てAPCを有効に出来なかった。

PHP Startup: Unable to load dynamic library apc.so (null) in Unknown on line 0

このエラー、Postgresのsoファイルも同じようにMakeしてモジュールとしてロードしようとした時にも出たんだよなぁ。かなり事例を探したけど、結局解決できなくて、Macで別にPostgresを使ったアプリを開発しなくてもいいからいいやって放置したんだった、、、


APCを有効にした時のパフォーマンス比較は、id:yandodさんの発表資料が詳しいのでそちらを参照下さい。

http://d.hatena.ne.jp/yandod/20080929/1222706633

2008-12-29

CakePHP1.2finalとRC3のパフォーマンス比較

2008/12/30追記

パフォーマンステストですが、今回のテスト環境で単純なhtmlファイルのみに対して多重アクセスして計測したところ9req/secというありえないぐらい低い数値になってしまったので、テスト環境に不備があるかもしれません。1月半ばまでアメリカに滞在していてノートPC1台しかない環境にいるため、それ以降で家に帰ったら自宅サーバで試してみます。


手元にCakePHP 1.2finalとRC3の環境があったので気になっていたパフォーマンスをチェックしてみました。

Cakephp Docのブログチュートリアル

http://book.cakephp.org/view/336/Creating-Post-Views

で、DBにInsertした3件の記事を一覧表示する単純な実装で、app以下は同じで、cakeフォルダのみ入れ替えてテストしてみました。どちらもCakeのDebugは0にしています。


テスト環境は、Core2Duo 2.4G, Mem 2G windows XP , XAMPPの環境に、同一ホストからabコマンドを使って計測してみました。

ab -c 30 -n 30 http://localhost/blog/index

負荷計測の場合、本当なら異なるホストから計測する方が良いのですが、今回はパフォーマンス向上の比較なのでそこまで厳密にやってません。計測端末上では、SkypeやらEclipaseやら、FireFoxやら色々と動かしたままやってます。

結果としては、APC OFFの状態で、それぞれ複数回計測して平均すると

Cake 1.2 Final 7req/sec
Cake 1.2 rc3 7req/sec

となり、ほぼパフォーマンスは変わらずでした。性能の最大値と最小値もほぼ同じぐらいでした。

たぶん、APC ONにしてもパフォーマンスの差はほとんどないと思います。