こんにちは、松本です。
3月の最終エントリ以後、暑すぎて ダラダラし過ぎました。Blogをちゃんと書くようにします。
今回はperlのフレームワーク "Sledge" でテンプレートエンジンの "Text::Xslate" を使います。
Template-Toolkitについて
Sledgeで利用するテンプレートエンジンは TT(Template-Toolkit) がデファクトスタンダードであります。
(HTML::Templateも使えますが・・・)
TTは、テンプレートエンジンとして非常に柔軟性が高く、大変に使いやすいのですが何せ、処理が重いです。
6A(シックス・アパート)のBlogサービスの、VoxもTemplate-Toolkitを利用しているらしいのですが
Template Toolkit: profile. Wow! Template Toolkit takes 60% of the request time.
との事で、リクエストの処理全体の6割をTTが占有してしまっているという驚愕の事実らしいです。
弊社でも ClearSilver 、 Text::MicroTemplate 、 Tenjiin などを Sledge に組み込めるか、試行錯誤してみたのですが
TTと全く違う文法で記述されたHTMLテンプレートが、プロジェクト毎に混在するとなると、運用面で人的負荷や稼動コストが増える可能性があったため、見送っていました。
- (参考)How we build Vox - SlideShare
- (参考2)Sledgeから利用する各種テンプレートエンジンの設定例 - ありんく Tech Wiki
Text::Xslate
Text::Xslate は、藤 吾郎さん が CPAN で公開されているモジュールで、精力的にUPDATEされているテンプレートエンジンです。
TTとほとんど同一の文法でHTMLテンプレートを記述することができ、更に高速動作するモジュールでして
先の 6割の処理の部分を抑える事ができるのでは?と期待大です。
- Text::Xslate
- Text::Xslate 公式ページ
TTの文法により近づけるために Text::Xslate::Bridge::TT2Like モジュールも併せて利用します。
インストール
cpanm で さっくりインストールです。
cpanm -S Text::Xslate Text::Xslate::Bridge::TT2Like
Sledgeのテンプレートクラス
ズバリ、以下のテンプレートクラスをPages.pmから呼び出しています。
Prog/Pages.pm (一部)
シンタックスハイライトを付けてある、全コードは こちら
sub create_template {
my ($self, $file) = @_;
my $tmpl = Proj::Template::Text::Xslate->new($file, $self);
return $tmpl;
}
Proj/Template/Text/Xslate.pm
シンタックスハイライトを付けてある、全コードは こちら
package Proj::Template::Text::Xslate;
use utf8;
use strict;
use warnings;
#use base qw/Sledge::Template/;
use Text::Xslate;
use Scalar::Util;
use vars qw($Tx);
$Tx = '';
sub new {
my($class, $file, $page) = @_;
bless {
_options => {
filename => $file,
},
_params => {
config => $page->create_config,
r => $page->r,
session => $page->session,
},
}, $class;
}
sub add_associate { Sledge::Exception::UnimplementedMethod->throw }
sub associate_namespace { Sledge::Exception::UnimplementedMethod->throw }
sub output {
my $self = shift;
#my %config = %{$self->{_options}};
#my $input = delete $config{filename};
my $input = delete $self->{'_options'}->{'filename'}
|| Sledge::Exception::TemplateNotFound->throw(
"No template file detected. Check your template path.",
);
if(!$Tx) {
my %config = %{$self->{_options}};
$config{syntax} = 'TTerse';
$config{header} = [ qw/commons.inc/ ];
$config{module} = [ qw/Text::Xslate::Bridge::TT2Like/ ],
$config{path} = [ $self->{'_params'}->{'config'}->tmpl_path, $self->{'_params'}->{'config'}->tmpl_path . '/includes' ];
$config{cache} = 1;
$config{cache_dir} = $self->{'_params'}->{'config'}->cache_dir . '/text_xslate_cache';
$config{type} = 'text';
$config{function} = {
nl2br => \&Text::Xslate::Bridge::TT2Like::html_line_break,
uri_escape => \&Text::Xslate::uri_escape,
};
$Tx = Text::Xslate->new(%config);
#warn "[ CREATE TX ]";
}
unless (-e $input) {
Sledge::Exception::TemplateNotFound->throw(
"No template file detected. Check your template path.",
);
}
$input =~ s@/path/to/proj/view/@@;
my $output = $Tx->render($input, $self->{'_params'});
$self->finalize;
return $output;
}
sub param {
my $self = shift;
if (@_ == 0) {
return keys %{$self->{'_params'}};
}
elsif (@_ == 1) {
return $self->{'_params'}->{$_[0]};
}
else {
while (my($key, $val) = splice @_, 0, 2) {
$self->{'_params'}->{$key} = $val;
}
}
}
sub finalize {
my $self = shift;
for my $key ($self->param()) {
if( ! ref( $self->{'_params'}->{$key} ) || $key eq 'session' || $key eq 'r' || $key eq 'config') { next; }
if (!Scalar::Util::isweak($self->{'_params'}->{$key})) {
#warn "[ WEAKEN ] ".$key;
eval { Scalar::Util::weaken($self->{'_params'}->{$key}) };
}
delete $self->{'_params'}->{$key};
}
}
1;
速度比較
Template-ToolkitからText::Xslateに変更することで、大よそ 150% ぐらい、リクエストの処理速度が向上しました。
今まで 100req/sec だったものが 150req/sec に高速化された形です。
気になった点、ハマッた点
- mod_perlのプロセスサイズが 120%ぐらい増えました。 メモリが少ない環境では要注意かも。
ハマッた点
Docsにも書いてある点がほとんどなので、ちゃんと読め!という部分なのですが・・・
- [% INCLUDE "header.inc" %] など、 "(ダブルクォーテーション)でファイル名を囲まないといけないです。
- TTのオプションに存在する、"ABSOLUTE" が使えないので INCLUDE内のファイルに明示的に変数を渡さなければならないので
[%- INCLUDE "header.inc" WITH FOO = 'ふー' -%]などとWITHで記述します。
- TTでいう、PROCESS、INSERT は使えないです。
- マクロを呼び出すときに、[% macro_func %] でなく、[% macro_func() %] と () を付ける必要があります。
- render($file,$param) で指定する $fileは path で指定された以下のファイルパスを指定します。(絶対パスではないです)
- TTの PRE_PROCESS は Text::Xslate の new時に渡す引数の header に相当します
まとめ
Template-Toolkitとほとんど同一の記法で、基本差し替えるだけで
Webアプリ全体の処理速度が向上しますので、是非ご利用されてみてはいかがでしょうか。
150%の処理速度向上が見込めましたので、次回プロジェクトでは試行してみたいと思います。








