2010年2月12日金曜日

symfony 1.4.1 fragment cache(cache関数)のよくわからない挙動について

 

テスト用のapp testを追加

symfony generate:app test
symfony generate:module test default

apps/test/config/settings.ymlのprodにcache:true追加。apps/test/modules/default/actions/actions.class.phpのexecuteindexをreturn sfView::SUCCESS;に書き換え。

1 この状態でアクセスしてみる。

ブラウザで/test.php/を開く。

キャッシュされたファイルを調べる。
find cache/test/prod/template/ -type f

(何も表示されない)

2 indexSuccess.phpでfragment cacheを使って見る。

例えばapps/test/modules/default/templates/indexSuccess.phpを下記の内容にする。

<?php if( !cache('cachename', 600) ):?> 
cache time - <?php echo date('Y-m-d H:i:s')?> 
<?php cache_save()?> 
<?php endif;?>

ブラウザで/test.php/を開く。

キャッシュされたファイルを調べる。
find cache/test/prod/template/ -type f

cache/test/prod/template/localhost/all/default/index/_sf_cache_key/cachename.cache - これは良いとして、、
cache/test/prod/template/localhost/all/default/index.cache - これは何?

 

3 GETで値を投げてみる。

ブラウザで/test.php/?a=1を開いてみる。
ブラウザで/test.php/?a=2を開いてみる。

キャッシュされたファイルを調べる。
find cache/test/prod/template/ -type f

cache/test/prod/template/localhost/all/default/index/_sf_cache_key/cachename.cache
cache/test/prod/template/localhost/all/default/index/a/1.cache - 増えてる!
cache/test/prod/template/localhost/all/default/index/a/2.cache - 増えてる!
cache/test/prod/template/localhost/all/default/index.cache


4 まとめ

もしかしたら根本的に勘違いをしているのかも。そもそも1.4だとhttp://www.symfony-project.org/jobeet/1_4/Propel/ja/21 に特にcache関数の説明がないからサポートしてない?

追記 1

symfony 1.0で同じ事をすると、
cache/test/prod/template/localhost/all/test.php/symfony/index/_sf_cache_key/cachename.cache
というファイルしかできない。個人的にはこれが理想。
現状だと、symfony1.4の挙動が仕様なのか、バグなのわからない。

cache()関数使用後に、sfViewCacheManager->isCachable(‘default/index’)するとこれがtrueを返す。symfony1.0だとそもそもcache()関数後(action実行後)にisCachableは呼び出されない。lazy_cache_key(ビューキャッシュのために遅延キャッシュキージェネレーション)の関係で後から呼び出されるのかもしれない。lazy_cache_keyの意味はわからないが、、

追記2

今のsfViewCacheManagerだと、複数回cache関数を実行すると一番最後に実行したcache()関数のlifetimeでdefault/indexのキャッシュが作成される。これは仕様としてどうなのか。(注:後から気付いたがこれは間違い)

プログラムを見た感じ、moduleとactionでisCachableを切り分けていて、cache関数を実行すると、currentのmoduleとactionでcacheがonになり、actionがキャッシュされてしまう。

追記3

sfCacheFilterのexecute()を$filterChain->execute();return;としてもキャッシュが生成される。どのタイミングで生成してるんだろう。余分に作られている(と思っている)キャッシュはactionキャッシュと同じものだが、上記のテストの方法で作った場合default/indexのcacheはenabled:falseになるので、sfCacheFilterがキャッシュチェック時(sfExecutionFilterの実行前)にはisCachableはfalseとなり、キャッシュを使用することはないし作ることに意味がないように見える。

追記4

sfFileCache::write()で書き込み状態を調べてみると、余分に作られている(と思っている)キャッシュは、ブラウザでリロードするたびに書き込まれる、、

追記5

余分に作られている(と思っている)キャッシュは、最終的にsfPHPView::render()の、
$content = $viewCache->setActionCache($uri, $content, $this->isDecorator() ? $this->getDecoratorDirectory().'/'.$this->getDecoratorTemplate() : false);
上記の部分で書き込まれている。setActionCache()はソースを見た感じ、そのアクションがisCacheableでwithLayoutの場合のみキャッシュとして保存するようになっている。本来であれば、cache.ymlで特にenabled: trueとしているわけでもないので、キャッシュとして保存されるはずはないが、cache関数を実行した時に実行されるaddCache関数がactionキャッシュのキャッシュ情報を上書きするような動作になっており、action cacheも保存ししまっているように見える。

 

全体的に見た感じバグっぽいが、、対応は後日検討。新たにcache関数の代わりのヘルパーを作るか、sfViewCacheManagerの動作を変えるか、sfPHPViewの動作を変えるかして対応することにする。

追記6

cache.ymlにてdefault/indexをenabled:trueを指定した場合cache/test/prod/config/module_default_config_cache.yml.phpに下記の内容が追加される。

$this->addCache($moduleName, 'index', array('withLayout' => false, 'lifeTime' => 600, 'clientLifeTime' => 600, 'contextual' => false, 'vary' => array ()));

ヘルパーのcache関数を実行した場合、下記のような内容が実行される。

$cache->addCache($params['module'], $params['action'], array('withLayout' => false, 'lifeTime' => $lifeTime, 'clientLifeTime' => $lifeTime, 'vary' => $vary));

この場合両者とも、module = default, action = index,となるため、cache関数を実行した場合もcache/indexをenable:trueとした場合と同じになり、default/indexのaction cacheが保存される事になる。

 

まとめ2

sfViewCacheManagerのソースを見た感じでは、module名とaction名のみを基準にキャッシュ管理をしており、独自の内部URI(default/indexのような)をもたないcacheは制御が行えず、action cacheも同時に保存してしまうような仕様なのかも知れない。
ただキャッシュファイルは保存されるが、sfCacheFilter実行時にはまだcacheヘルパーは実行されておらず、addCacheされていないためそのキャッシュファイルは使用されない。ようするにキャッシュファイルがあってもsfExecutionFilterは実行されるし、保存されたaction cacheは特に意味はない。

対策!

現状1.0から1.4へ移行しようとしているサイトは、1.0で運用している現在のキャッシュファイルだけでも数十ギガあるため、このまま1.4に置き換えるとそれだけでさらにキャッシュファイルのサイズが数倍になってしまうことが予想される。

対策として、CacheHelperの動作を変更した。ソースは後日アップ予定。

0 件のコメント:

コメントを投稿