Technofara

Golangエンジニア!仕事で必要になって勉強した事とか、新しい事とか色々まとめたりを緩くやります。技術系と思考系だけにしておきます、

え、まだPHPテンプレートエンジン使ってないの?(twig編)

ごめんなさい。まだ使ってません><

最近までテンプレートエンジンは重くなる原因と思って、、使ってませんでした。 あとは使用しているフレームワークの標準が使いにくすぎて、、、

symphonyとかだとtwig使ってるのに、、 そんな訳で、twigって実際どうなの?テンプレートエンジンってどうなの?って調べてみました。

今回検証する内容は * twig: テンプレートのコンパイルキャッシュ有り -> 初回のみテンプレートのコンパイル * twig: テンプレートのコンパイルキャッシュ無し -> 毎回テンプレートのコンパイル * php include: includeするだけで、テンプレートには<?php echo $hoge; ?>形式

この3パターンで検証してみます。

最近のテンプレートエンジンは、phpへのコンパイル後にファイル(メモリ)キャッシュをしてくれるんですね。。それならそこまで重さとか気にする必要なさそうですね。 でもそれを判断するのはまだ早い!!とりあえず検証!

twigの準備

composer登場、、これはそのうち調べよう

$ curl -sS https://getcomposer.org/installer | php

$ cat composer.json 
{
     "require": {
         "twig/twig": "1.*"
     }
 }

php composer.phar install

準備おわり

今回登場するファイルの説明

php + includeの場合

テンプレート

<html>
<head>
</head>
<body>
テンプレートテスト
<?php foreach($users as $key => $user){ ?>
 * <?php echo $user['name']; ?><br>
<?php } ?>

まぁこんな感じで、html内部にphpを書くことになっちゃいますよね。 可読性が悪いこと。。。

検証処理

<?php                                                         
$users = array();                                             
                                                              
for($i=0; $i < 100; $i++ ){                                   
    array_push($users, array('name' => 'shinofara No.' . $i));
}                                                             
                                                              
include('templates/index2.html');                             
                                                              
echo "\n";                                                    
echo 'Memory: '. (memory_get_usage() / 1000 / 1000 ) ."M\n";  

こんな感じで、テンプレートに渡す配列を作って、inculude そして、使ったメモリを出力。 php使い始めはこんな感じになるかな?

twigを使う場合

テンプレート

<html>
<head>
</head>
<body>
テンプレートテスト
{% for key, user in users %}
 * {{loop.index }}: {{ user.name }}
{% endfor %}
</body>

phpらしさが消えて、include時より可読性は上がった様に思える! すっきりした感じ?

キャッシュ有り版の処理

<?php                                                         
require_once 'vendor/autoload.php';                           
                                                              
$loader = new Twig_Loader_Filesystem('templates');            
$twig = new Twig_Environment($loader, array(                  
    'cache' => 'compilation_cache',                           
));                                                           
                                                              
$users = array();                                             
                                                              
for($i=0; $i < 100; $i++ ){                                   
    array_push($users, array('name' => 'shinofara No.' . $i));
}                                                             
                                                              
echo $twig->render('index.html', array('users' => $users));   
                                                              
echo "\n";                                                    
echo 'Memory: '. (memory_get_usage() / 1000 / 1000 ) ."M\n";  

templates以下のファイルを読み込んで、コンパイル結果を compilation_cacheに書き出しますよー。 処理自体は、include版と同じ

キャッシュ無し版の処理

<?php                                                         
require_once 'vendor/autoload.php';                           
                                                              
$loader = new Twig_Loader_Filesystem('templates');            
$twig = new Twig_Environment($loader, array());               
                                                              
$users = array();                                             
                                                              
for($i=0; $i < 100; $i++ ){                                   
    array_push($users, array('name' => 'shinofara No.' . $i));
}                                                             
                                                              
echo $twig->render('index.html', array('users' => $users));   
                                                              
echo "\n";                                                    
echo 'Memory: '. (memory_get_usage() / 1000 / 1000 ) ."M\n";  

キャッシュしてないだけで、処理は一つ前と同じ

では、検証開始!

php + include の場合

$time php include_version.php
Memory: 0.823752M

real    0m0.075s
user    0m0.057s
sys 0m0.015s

twig キャッシュ無し

$time php twig_nocache.php
Memory: 4.358264M

real    0m0.112s
user    0m0.085s
sys 0m0.022s

twig キャッシュ有り(初回コンパイルも含む)

キャッシュ有りの場合は、初回にコンパイルをする場合、しない場合で確認します。

Memory: 4.358664M

real    0m0.111s
user    0m0.085s
sys 0m0.023s

twig キャッシュ有り(コンパイル済み)

Memory: 1.927904M

real    0m0.083s
user    0m0.065s
sys 0m0.016s

結論

今回は、小さいテンプレート、少しのデータ量で検証したので 全然差が出ない、もしくは想定している結果が帰って来ないかなーとおもってたけど 意外と差がでたのでよかった。

速度としては、php + includeが早い!そのかわり可読性が低いので、保守が辛い、、マークアップエンジニア、デザイナがこのファイルを見るのはつらそう。。

キャッシュナシと、アリに関しては、検証方法のミスなのか差が無かった。。。 デルレベルじゃなかったからかなー。。 でも、コンパイル済み版では、コンパイルする(キャッシュ有り、無し含めて)より余裕で早くなった。

大規模開発とかになってくると、キャッシュ有り無しで差が出てくることになると思うし。 分業とかになってくるとhtmlの可読性も大事になってくる。

で?

テンプレートコンパイルが初回は発生するので、初回速度はやや落ちるもののキャッシュ化してしまえば、include並に速度は出る事がわかったので テンプレートエンジン(今回はtwig)の使用もありだと思いました。