Elementキャッシュ
ホームなど、ポータル系の画面で
新着情報エリア
自分の情報エリア
RSS情報エリア
・・・などのように更新タイミングが分かれている場合は、Elementキャッシュがよいようです。
Elementキャッシュ導入で、参考にしたのは以下。
http://text.tklabo.net/blog/8/view-cache
Elementキャッシュ導入で、表示が1.4回/秒から、3.9回/秒に向上しました*1
A:ユーザ表示
B:自分の新着
C:全体の新着
で、Cのみログイン/未ログインを問わず、全員で共通表示します。
A/B/Cを、それぞれElementキャッシュしました。
ポイントは、 A/Bは、キャッシュ名(key)にセッションIDをいれた点です。
B(Aも同様)
echo $this->renderElement('character_picture_table', array( 'header' => sprintf(__("%s's Characters", true), $target_user['User']['name']), 'characters' => $target_user_characters, (中略) + 'cache' => array( + 'time' => time() + Configure::read('Cache.expire'), + 'key' => $session->id(), + ) ));
C
echo $this->renderElement('character_picture_table', array( 'header' => __('Latest Characters', true), 'characters' => $public_characters, (中略) + 'cache' => array( + 'time' => time() + Configure::read('Cache.expireShort'), + 'key' => null, + ) ));
オプションパラメータに $options['cache']['key']を指定すると、キャッシュファイル名が
element_[key]_[エレメントファイル名]
となります。
keyにセッションIDを入れることで、それぞれのユーザごとに
「ホーム用自分の新着」キャッシュを持たせる事ができます。
実際のキャッシュファイル作成状態
キャッシュが無い状態で、未ログインユーザがアクセス。
[cake@cake chara-shee]$ ls -l app/tmp/cache/views/
合計 44
まず、Cのキャッシュができます。
ここから、ユーザ1でログイン。
[cake@cake chara-shee]$ ls -l app/tmp/cache/views/
合計 44
- rw-r--r-- 1 apache apache 3163 7月 16 15:15 element__character_picture_table
- rw-r--r-- 1 apache apache 2800 7月 16 15:21 element_ekg7u0r93oa1j486f1k99mkpe7_character_picture_table
- rw-r--r-- 1 apache apache 295 7月 16 15:21 element_ekg7u0r93oa1j486f1k99mkpe7_home_left
- rw-rw-r-- 1 cake cake 0 7月 13 15:05 empty
ユーザ1用のA/Bのキャッシュが作成されます。
この時、Cは更新されてないのがポイント。
さらに、別窓からユーザ2でアクセスすると、ユーザ2用のキャッシュが別途作成されます。
[cake@cake chara-shee]$ ls -l app/tmp/cache/views/
合計 44
- rw-r--r-- 1 apache apache 3163 7月 16 15:15 element__character_picture_table
- rw-r--r-- 1 apache apache 2800 7月 16 15:21 element_ekg7u0r93oa1j486f1k99mkpe7_character_picture_table
- rw-r--r-- 1 apache apache 295 7月 16 15:21 element_ekg7u0r93oa1j486f1k99mkpe7_home_left
- rw-r--r-- 1 apache apache 2868 7月 16 15:23 element_l6o3bnorfrm87r1nsdlnlm4sa5_character_picture_table
- rw-r--r-- 1 apache apache 319 7月 16 15:23 element_l6o3bnorfrm87r1nsdlnlm4sa5_home_left
- rw-rw-r-- 1 cake cake 0 7月 13 15:05 empty
仕上げに、ユーザ情報の更新/削除/ログアウトがあった場合のキャッシュ削除を入れて完成*2。
ソース差分抜粋
app/models/app_model.php + + /* キャッシュ削除 */ + // ホーム関連 + function deleteCacheHome() + { + $this->deleteCacheLastCharacters(); + $this->deleteCacheAnonymousHome(); + $this->deleteCacheMyHome(); + } + + // 最近更新されたキャラクター + function deleteCacheLastCharacters() + { + @unlink(CACHE.'views'.DS.'element__character_picture_table'); + } + + // 未ログインホーム + function deleteCacheAnonymousHome() + { + @unlink(CACHE.'views'.DS.'element__home_right'); + } + + // マイホーム + function deleteCacheMyHome() + { + $Session = CorePlus::set_behavoir('Session'); + + if (!$Session->id()) { + return false; + } + + @unlink(CACHE.'views'.DS.'element_'.$Session->id().'_character_picture_table'); + @unlink(CACHE.'views'.DS.'element_'.$Session->id().'_home_left'); + } + } app/models/behaviors/session.php @@ -0,0 +1,27 @@ +<?php +class SessionBehavior extends CakeSession { + function setup(&$Model,$config = array()){ + $base = null; + $start = Configure::read('Session.start'); + extract($config); + + $session = null; + if(ClassRegistry::isKeySet('CakeSession')){ + $session = ClassRegistry::getObject('CakeSession'); + }else{ + App::import('Core','CakeSession'); + $session = new CakeSession($base,$start); + + ClassRegistry::addObject('CakeSession',$session); + } + + $Model->Session = $session; + if($start && !$Model->Session->started()){ + $Model->Session->start(); + } + } + + function id($id = null) { + return parent::id($id); + } +} app/models/user.php @@ -135,6 +135,16 @@ class User extends AppModel { { return parent::beforeSave($options); } + function afterSave($created) { + $this->deleteCache4User(); + + return parent::afterSave($created); + } + function afterDelete() { + $this->deleteCache4User(); + + return parent::afterDelete(); + } @@ -156,4 +166,13 @@ class User extends AppModel { return parent::betweenWrapper($check[0], $idLength['min'], $idLength['max']); } + + /* キャッシュ削除 */ + function deleteCache4User() + { + // Home + $this->deleteCacheHome(); + } + + } app/views/elements/home_right.ctp @@ -17,7 +17,10 @@ 'action' => 'index', $target_user['User']['id'], ), - + 'cache' => array( + 'time' => time() + Configure::read('Cache.expire'), + 'key' => $session->id(), + ) )); ?> <?php endif; ?> @@ -37,7 +40,10 @@ 'controller' => 'characters', 'action' => 'index' ), - + 'cache' => array( + 'time' => time() + Configure::read('Cache.expireShort'), + 'key' => null, + ) )); ?> app/views/users/index.ctp @@ -1,14 +1,23 @@ <div id="home" class="layout2colums users view"> <?php -if (!empty($user['User']['id'])) { - echo $this->renderElement('home_left', array( - 'user' => $user, +$key = null; + +if ($user['User']['id']) { + $key = $session->id(); + + echo $this->element('home_left', array( + 'target_user' => $user, 'owner' => true, + 'cache' => array( + 'time' => time() + Configure::read('Cache.expire'), + 'key' => $key, + ) )); }
*1:ApacheBench測定。向上の度合いは内容や環境によります
*2:モデルでセッション情報の取得は、http://d.hatena.ne.jp/hiromi2424/20100203 を参考にしました