memcachedとSmarty
Simplateを試す
公式のインストールの項目の通り、ソースからインストールした。このときにエスケープ処理が欲しかったので
自動でエスケープするパッチを当てた。
バージョンが0.41だったが問題なく動作した。
使えるプロパティとメソッドの一覧はとても便利。
下記のコードとテンプレートを実行してSmartyと比べてどの程度の性能が出るか測ってみた。
実行環境はVMWareServer上のCentosにphp5.2.5を入れたものを使用した。GETで実行回数を渡して数千回くらい実行してみた。
実験に使用したコード
$start = microtime(true); for( $i=0; $i<$loopCount; ++$i ){ $simplate = new Simplate(); $simplate->force_compile = $forceCompile; $simplate->template_dir = '../../templates'; $simplate->compile_dir = 'template_c_sim'; $simplate->left_delimiter = '[--'; $simplate->right_delimiter = '--]'; $var1 = "Hello World<><<><></br>"; $var2 = "Asial"; $array1 = array('日', '月', '火', '水', '木', '金', '土'); $array3 = array('日', '月', '火', '水', '木', '金', '土'); $array4 = array('日', '月', '火', '水', '木', '金', '土'); $array5 = array('日', '月', '火', '水', '木', '金', '土'); $array6 = array('日', '月', '火', '水', '木', '金', '土'); $simplate->assign('var1', $var1); $simplate->assign('var2', $var2); $simplate->assign('array', $array1); $simplate->assign('array2', $array3); $simplate->assign('array3', $array4); $simplate->assign('array3', $array5); $simplate->assign('array3', $array6); $simplate->assign('array3', array('hoge'=>'aaaaaaaaa')); $simplate->fetch('debugm.php'); } $end = microtime(true); echo "simplate : ".($end - $start)." msec<br>"; $start = microtime(true); for( $i=0; $i<$loopCount; ++$i ){ $smarty = new Smarty(); $smarty->force_compile = $forceCompile; $smarty->template_dir = '../../templates'; $smarty->compile_dir = 'template_c'; $smarty->left_delimiter = '[--'; $smarty->right_delimiter = '--]'; $var1 = "Hello World<><<><></br>"; $var2 = "Asial"; $array1 = array('日', '月', '火', '水', '木', '金', '土'); $array3 = array('日', '月', '火', '水', '木', '金', '土'); $array4 = array('日', '月', '火', '水', '木', '金', '土'); $array5 = array('日', '月', '火', '水', '木', '金', '土'); $array6 = array('日', '月', '火', '水', '木', '金', '土'); $smarty->assign('var1', $var1); $smarty->assign('var2', $var2); $smarty->assign('array', $array1); $smarty->assign('array2', $array3); $smarty->assign('array3', $array4); $smarty->assign('array3', $array5); $smarty->assign('array3', $array6); $smarty->assign('array3', array('hoge'=>'aaaaaaaaa')); $smarty->fetch('debugm.php'); } $end = microtime(true); echo "smarty : ".($end - $start)." msec<br>";
テンプレートファイル
<html> <head></head> <body> <p> [-- $var1 --] [--foreach from=$array key=key item=value name=array --] [--$key--]:[--$value--]<br/> <br/> [--/foreach--] [-- $array2.hoge --] [--foreach from=$array3 key=key item=value name=array --] [--$key--]:[--$value--]<br/> <br/> [--/foreach--] [--foreach from=$array4 key=key item=value name=array --] [--$key--]:[--$value--]<br/> <br/> [--/foreach--] [--foreach from=$array5 key=key item=value name=array --] [--$key--]:[--$value--]<br/> <br/> [--/foreach--] [--foreach from=$array6 key=key item=value name=array --] [--$key--]:[--$value--]<br/> <br/> [--/foreach--] </p> <hr/>
Simplate VS Smartyの結果
今の環境で実行した結果、Smartyの方がSimplateよりも2倍早かった(VMWareの時間は精神と時の部屋状態なので計測値はあてにならない)
実行順序を変えても変わらなかったので、Simplateの方が遅いのだろうと判断した。
force_compileフラグをtrueにするととてもSmartyは遅いのでSimplateの方がテンプレートのコンパイルは早いことも確認できた。
また、fetchメソッドをコメントアウトするとSimplateの方が早いことも確認できた。
最終的にはcompile_checkをfalseにするだけでも十分な効果が確認できたのでSmartyでも十分使えるじゃないかという話にまとまった。
memcachedを使う
次にファイルのIOを無くせば早いんじゃないかと思って、memcachedをインストールして数値を取ってみた。
PHPで使うにはPECLにmemcachedのライブラリがあるのでそれを使えば実行ができる。しかし、php-libmemcachedの速度調査 get()とset()編によると
php-libmemcachedというのを使うと早いとあったので、こっちを使うことに決めた。
いくつか参考にしたページ一覧
memcachedで実験
無事GREEのサンプルコードが実行でき、memcachedが動いていることが確認できたのでSmartyをパワーアップさせることが出来るかどうか試すことにした。
Smartyのコンパイル済みファイルをmemcachedに乗っけてしまえばFileIOがなくなって幸せになれるんじゃないか???
という仮説の検証のために下記のコードを実行した。Smartyを継承したクラスを作り、そこにmemcachedからデータを取れるようなら取るように書き換えた。(今回はfetchするだけの実験をしたのでfetchだけ改造した)
注意しなければいけないのはeval関数。Smartyのコンパイル済みテンプレートファイルはinclude関数を実行したときに一発で出力できるようにPHPタグを含んでいるのでそのまま実行するとParse Errorで怒られる。
eval関数のドキュメントを見ているとPHPの終了タグを含めることができるとわかったので、
evalに渡す文字列にPHP終了タグを付与して実行した。
実験に使ったコード
class SmartyExt extends Smarty{ function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false){ $assignMemchached = false; $memcached = new Memcached(); $memcached->addserver('localhost', 11211); $_smarty_compile_path = $this->_get_compile_path($resource_name); ob_start(); if ($this->_is_compiled($resource_name, $_smarty_compile_path) || $this->_compile_resource($resource_name, $_smarty_compile_path)) { if( $cache = $memcached->get($resource_name) ){ eval( "?>".$cache ); }else{ include($_smarty_compile_path); $assignMemchached = true; if( $assignMemchached ) $memcached->set($resource_name, file_get_contents($_smarty_compile_path)); } } $_smarty_results = ob_get_contents(); ob_end_clean(); return $_smarty_results; } }