Text::MicroTemplateの速度を簡単にベンチマーク

2009 年 11 月 15 日 oinume コメント 2 件

2009/11/15 追記tokuhiromさんのコメントを受けて、Text::MicroTemplate以外のテンプレートファイルにHTMLエスケープの処理を追加してベンチマークを取り直しています。

Perlのテンプレートエンジンでどれを使おうか悩んでいるので、Text::MicroTemplateをはじめとする以下のテンプレートエンジンの速度を簡単にベンチマークしてみました。

下記の要因で単純に比較できない部分もあるので、これを鵜呑みにしないでなるべく自身のユースケースの延長でもベンチマークを取ることをお奨めします。あくまで参考値ということで。

  • そもそも持っている機能が全然違うので単純に比較できない
  • 実際のテンプレートファイルはもっと複雑なはず
  • utf8 flagの処理入れる場合もある

ではとりあえず結果から。

キャッシュなし

$ perl template_speed_file.pl 3000 0
Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  5 wallclock secs ( 4.60 usr +  0.09 sys =  4.69 CPU) @ 639.66/s (n=3000)
HT::Compiled: 10 wallclock secs (10.56 usr +  0.10 sys = 10.66 CPU) @ 281.43/s (n=3000)
   HT::Pro:  1 wallclock secs ( 0.20 usr +  0.04 sys =  0.24 CPU) @ 12500.00/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  2 wallclock secs ( 2.39 usr +  0.07 sys =  2.46 CPU) @ 1219.51/s (n=3000)
        TT: 10 wallclock secs ( 9.65 usr +  0.17 sys =  9.82 CPU) @ 305.50/s (n=3000)
                Rate HT::Compiled          TT          HT          MT    HT::Pro
HT::Compiled   281/s           --         -8%        -56%        -77%       -98%
TT             305/s           9%          --        -52%        -75%       -98%
HT             640/s         127%        109%          --        -48%       -95%
MT            1220/s         333%        299%         91%          --       -90%
HT::Pro      12500/s        4342%       3992%       1854%        925%         --

キャッシュあり

コードを見てもらえばわかるのですが、「キャッシュあり」とは具体的には

  • テンプレートのインスタンスを作るのは最初の1回だけ(キャッシュなしの場合は毎回作っている)
  • テンプレートエンジンに対して、「キャッシュあり」とコンストラクタで指令

ということになります。

$ perl template_speed_file.pl 3000 1
Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  3 wallclock secs ( 2.69 usr +  0.00 sys =  2.69 CPU) @ 1115.24/s (n=3000)
HT::Compiled:  0 wallclock secs ( 0.28 usr +  0.00 sys =  0.28 CPU) @ 10714.29/s (n=3000)
            (warning: too few iterations for a reliable count)
   HT::Pro:  0 wallclock secs ( 0.13 usr +  0.02 sys =  0.15 CPU) @ 20000.00/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  1 wallclock secs ( 0.22 usr +  0.01 sys =  0.23 CPU) @ 13043.48/s (n=3000)
            (warning: too few iterations for a reliable count)
        TT:  1 wallclock secs ( 1.84 usr +  0.00 sys =  1.84 CPU) @ 1630.43/s (n=3000)
                Rate          HT          TT HT::Compiled          MT    HT::Pro
HT            1115/s          --        -32%         -90%        -91%       -94%
TT            1630/s         46%          --         -85%        -87%       -92%
HT::Compiled 10714/s        861%        557%           --        -18%       -46%
MT           13043/s       1070%        700%          22%          --       -35%
HT::Pro      20000/s       1693%       1127%          87%         53%         --
  • HTML::Template::Proが爆速!
  • Text::MicroTemplateは、キャッシュなしだとそこそこ、キャッシュありはかなり速い部類に入るようです。キャッシュありだとHTML::Template::Proには及ばないものの、かなり速いです。
  • HTML::Template::Compiledはキャッシュを無効にするとTTより遅いという結果ですが、キャッシュを有効にすると猛烈に速くなるようです。ソースが追えてないのですが、中でガチンコにキャッシュしてるのでしょうか。
  • たぶん一番使われているTTはよく「遅い」と言われていますが、キャッシュを有効にすると意外にもHTML::Templateより速くなりました。

というのがポイントだと思います。この結果だけで判断すると、HTML::Template::Proは神がかり的な速さなのですが、そもそもPerlのコードをテンプレートに記述できず自由度は低いので(*1)、使う場合にはそれなりに不便さを覚悟した方がよいと思います。「便利さ」という点だとText::MicroTemplateはテンプレート内にPerlのコードが書ける分かなり自由度が高い、かつ速度もいい感じでバランスが取れていると言えます。

*1) Perlのコードをテンプレートに書けてしまっていいのかどうかは使う人次第だと思いますが

以下にソースを載せておきます。テストに使ったマシンはUbuntu 9.04, perl 5.10.0, CPUが Athlon Dual Core Processor 5050e です。

template_speed_file.pl

#!/usr/bin/env perl
 
use strict;
use warnings;
use HTML::Template;
use HTML::Template::Compiled speed => 1;
use HTML::Template::Pro;
use Template;
use Text::MicroTemplate::File;
 
use Benchmark qw(timethese cmpthese);
 
my @LANGUAGES = (
    { language => 'Perl', ll => 1 },
    { language => 'Ruby', ll => 1 },
    { language => 'Python', ll => 1 },
    { language => 'PHP', ll => 1 },
    { language => 'Java' },
    { language => 'C' },
    { language => 'C++' },
    { language => 'C#' },
    { language => 'VB' },
    { language => 'VB.NET' },
    { language => 'ASP.NET' },
    { language => 'Delphi' },
    { language => 'Erlang' },
    { language => 'Scala', ll => 1 },
    { language => 'Go' },
);
my $count = shift @ARGV || 1000;
my $cache = shift @ARGV || 0;
 
my $mt = undef;
sub mt {
    my %args = (use_cache => $cache);
    if ($cache) {
        $mt ||= Text::MicroTemplate::File->new(%args);
    } else {
        $mt = Text::MicroTemplate::File->new(%args);
    }
 
    my $s = $mt->render_file(
        'template_speed_file.mt',
        {
            page_title => 'LL Programming languages',
            languages => \@LANGUAGES,
        }
    )->as_string;
}
 
my $ht = undef;
sub ht {
    my %args = (
        filename => 'template_speed_file.ht',
        case_sensitive => 1,
        die_on_bad_params => 0,
        cache => $cache,
    );
    if ($cache) {
        $ht ||= HTML::Template->new(%args);
    } else {
        $ht = HTML::Template->new(%args);
    }
    $ht->param(
        page_title => 'LL Programming languages',
        languages => \@LANGUAGES,
    );
    my $s = $ht->output;
}
 
my $htc = undef;
sub htc {
    my %args = (
        filename => 'template_speed_file.ht',
        case_sensitive => 1,
        die_on_bad_params => 0,
        cache => $cache,
    );
    if ($cache) {
        $htc ||= HTML::Template::Compiled->new(%args);
    } else {
        $htc = HTML::Template::Compiled->new(%args);
    }
    $htc->param(
        page_title => 'LL Programming languages',
        languages => \@LANGUAGES,
    );
    my $s = $htc->output;
}
 
my $htp = undef;
sub htp {
    my %args = (
        filename => 'template_speed_file.ht',
        case_sensitive => 1,
        die_on_bad_params => 0,
        cache => $cache,
    );
    if ($cache) {
        $htp ||= HTML::Template::Pro->new(%args);
    } else {
        $htp = HTML::Template::Pro->new(%args);
    }
    $htp->param(
        page_title => 'LL Programming languages',
        languages => \@LANGUAGES,
    );
    my $s = $htp->output;
}
 
my $tt = undef;
sub tt {
    if ($cache) {
        $tt ||= Template->new(
            CACHE_SIZE => $cache ? undef : 0,
        );
    } else {
        $tt = Template->new;
    }
    $tt->process(
        'template_speed_file.tt',
        {
            page_title => 'LL Programming languages',
            languages => \@LANGUAGES,
        },
        \my $out,
    ) or die $tt->error() . "\n";
}
 
# main
my $comp = timethese(
    $count,
    {
        'MT' => \&mt,
        'HT' => \&ht,
        'HT::Pro' => \&htp,
        'HT::Compiled' => \&htc,
        'TT' => \&tt,
    }
);
cmpthese $comp;

template_speed_file.mt – Text::MicroTemplate用のファイル

? my $p = $_[0];
<html>
<head><title>Programming languages</title></head>
<body>
<h1><?= $p->{page_title} ?></h1>
<br />
<ul>
? for my $language (@{ $p->{languages} }) {
<li><?= $language->{language} ?></li>
? }
</ul>
</body>
</html>

template_speed_file.ht – HTML::Template::*用のファイル

<html>
<head><title>Programming languages</title></head>
<body>
<h1><TMPL_VAR NAME=page_title ESCAPE=HTML></h1>
<br />
<ul>
<TMPL_LOOP NAME=languages>
<li><TMPL_IF NAME=ll>*</TMPL_IF><TMPL_VAR NAME=language ESCAPE=HTML></li>
</TMPL_LOOP>
</ul>
</body>
</html>

template_speed_file.tt – Template::Toolkit用のファイル

<html>
<head><title>Programming languages</title></head>
<body>
<h1>[% page_title | html %]</h1>
<br />
<ul>
[% FOREACH language IN languages %]
<li>[% language.language | html %]</li>
[% END %]
</ul>
</body>
</html>

HTMLエスケープあり/なしのスピードについて

tokuhiromさんのコメントにあるように、Text::MicroTemplateは自動でHTMLエスケープがかかる一方、他のテンプレートエンジンでは手動でやる必要があるので、HTMLエスケープを入れて測り直してみました。ちなみに上に載せているベンチの結果は、HTMLエスケープを入れたものになっています。

特筆すべきなのは、HTML::Template::CompiledがキャッシュありかつHTMLエスケープありの場合、HTMLエスケープなしに比べてパフォーマンスがかなり劣化している点です。(その他はちょっとずつパフォーマンスが劣化していますね)。

キャッシュなしかつHTMLエスケープなし

$ perl template_speed_file.pl 3000 0
Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  4 wallclock secs ( 3.85 usr +  0.10 sys =  3.95 CPU) @ 759.49/s (n=3000)
HT::Compiled: 10 wallclock secs ( 9.99 usr +  0.09 sys = 10.08 CPU) @ 297.62/s (n=3000)
   HT::Pro:  1 wallclock secs ( 0.21 usr +  0.02 sys =  0.23 CPU) @ 13043.48/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  2 wallclock secs ( 2.35 usr +  0.05 sys =  2.40 CPU) @ 1250.00/s (n=3000)
        TT:  8 wallclock secs ( 7.83 usr +  0.15 sys =  7.98 CPU) @ 375.94/s (n=3000)
                Rate HT::Compiled          TT          HT          MT    HT::Pro
HT::Compiled   298/s           --        -21%        -61%        -76%       -98%
TT             376/s          26%          --        -51%        -70%       -97%
HT             759/s         155%        102%          --        -39%       -94%
MT            1250/s         320%        233%         65%          --       -90%
HT::Pro      13043/s        4283%       3370%       1617%        943%         --

キャッシュなしかつHTMLエスケープあり

Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  5 wallclock secs ( 4.60 usr +  0.09 sys =  4.69 CPU) @ 639.66/s (n=3000)
HT::Compiled: 10 wallclock secs (10.56 usr +  0.10 sys = 10.66 CPU) @ 281.43/s (n=3000)
   HT::Pro:  1 wallclock secs ( 0.20 usr +  0.04 sys =  0.24 CPU) @ 12500.00/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  2 wallclock secs ( 2.39 usr +  0.07 sys =  2.46 CPU) @ 1219.51/s (n=3000)
        TT: 10 wallclock secs ( 9.65 usr +  0.17 sys =  9.82 CPU) @ 305.50/s (n=3000)
                Rate HT::Compiled          TT          HT          MT    HT::Pro
HT::Compiled   281/s           --         -8%        -56%        -77%       -98%
TT             305/s           9%          --        -52%        -75%       -98%
HT             640/s         127%        109%          --        -48%       -95%
MT            1220/s         333%        299%         91%          --       -90%
HT::Pro      12500/s        4342%       3992%       1854%        925%         --

キャッシュありかつHTMLエスケープなし

$ perl template_speed_file.pl 3000 1
Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  3 wallclock secs ( 2.50 usr +  0.00 sys =  2.50 CPU) @ 1200.00/s (n=3000)
HT::Compiled:  0 wallclock secs ( 0.15 usr +  0.00 sys =  0.15 CPU) @ 20000.00/s (n=3000)
            (warning: too few iterations for a reliable count)
   HT::Pro:  0 wallclock secs ( 0.10 usr +  0.04 sys =  0.14 CPU) @ 21428.57/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  0 wallclock secs ( 0.21 usr +  0.00 sys =  0.21 CPU) @ 14285.71/s (n=3000)
            (warning: too few iterations for a reliable count)
        TT:  1 wallclock secs ( 1.19 usr +  0.01 sys =  1.20 CPU) @ 2500.00/s (n=3000)
                Rate          HT          TT          MT HT::Compiled    HT::Pro
HT            1200/s          --        -52%        -92%         -94%       -94%
TT            2500/s        108%          --        -82%         -87%       -88%
MT           14286/s       1090%        471%          --         -29%       -33%
HT::Compiled 20000/s       1567%        700%         40%           --        -7%
HT::Pro      21429/s       1686%        757%         50%           7%         --

キャッシュありかつHTMLエスケープあり

Benchmark: timing 3000 iterations of HT, HT::Compiled, HT::Pro, MT, TT...
        HT:  3 wallclock secs ( 2.69 usr +  0.00 sys =  2.69 CPU) @ 1115.24/s (n=3000)
HT::Compiled:  0 wallclock secs ( 0.28 usr +  0.00 sys =  0.28 CPU) @ 10714.29/s (n=3000)
            (warning: too few iterations for a reliable count)
   HT::Pro:  0 wallclock secs ( 0.13 usr +  0.02 sys =  0.15 CPU) @ 20000.00/s (n=3000)
            (warning: too few iterations for a reliable count)
        MT:  1 wallclock secs ( 0.22 usr +  0.01 sys =  0.23 CPU) @ 13043.48/s (n=3000)
            (warning: too few iterations for a reliable count)
        TT:  1 wallclock secs ( 1.84 usr +  0.00 sys =  1.84 CPU) @ 1630.43/s (n=3000)
                Rate          HT          TT HT::Compiled          MT    HT::Pro
HT            1115/s          --        -32%         -90%        -91%       -94%
TT            1630/s         46%          --         -85%        -87%       -92%
HT::Compiled 10714/s        861%        557%           --        -18%       -46%
MT           13043/s       1070%        700%          22%          --       -35%
HT::Pro      20000/s       1693%       1127%          87%         53%         --
カテゴリー: Perl タグ:

PHPでFatal error: Allowed memory size of …が出た場合の対処方法

2009 年 11 月 7 日 oinume コメントはありません

あまりPHPのことわからないのですが、WordPressで

Fatal error: Allowed memory size of 8388608 bytes exhausted

というエラーメッセージが出ました。ぐぐると「php.iniのmemory_limitを64Mとか大きな値に設定すべし」とあるのですが、Ubuntuの /usr/share/php5/php.ini を

memory_limit = 64M

と直しても改善しませんでした。で、さらに調べてみるとどうやら /etc/php5/apache2/php.ini なんていうファイルが… これを上記と同じように64Mにしてapacheを再起動すると、めでたくエラーは出なくなりました。紛らわしいからphp.iniは一つにしておいてほしい…

カテゴリー: Apache, PHP タグ: ,

キーボードショートカットでMacをシステム終了

2009 年 11 月 7 日 oinume コメントはありません

いっつも忘れるのでメモ。Macをキーボードショートカットだけで終了する方法はControl + Option + Command + Eject 。右手でControlとOptionを押して、左手でCommand + Ejectを押す感じにしています。

カテゴリー: Mac タグ:

Perlで楽天ブックスジャンル検索APIを使う

2009 年 9 月 23 日 oinume コメントはありません

PerlでAmazon Product Advertising APIのBrowseNodeLookupを行なうの楽天版です。Amazon Product Advertising APIはRESTしかないのですが、楽天ウェブサービスはRESTとJSONに対応しているので、今回はJSONを使ってみます。

(ファイル名はsample_books_genre_search.pl)

#!/usr/bin/env perl
 
use strict;
use warnings;
use Data::Dumper qw(Dumper);
use JSON::Syck qw(Load);
use LWP::UserAgent;
use URI;
 
my $uri = URI->new('http://api.rakuten.co.jp/rws/2.0/json');
$uri->query_form(
    developerId => 'Your Developer ID',
    operation => 'BooksGenreSearch',
    version => '2009-03-26',
    booksGenreId => shift || '000',
);
 
my $ua = LWP::UserAgent->new;
my $res = $ua->get($uri);
 
$Data::Dumper::Indent = 1;
if ($res->is_success) {
    print Dumper(Load($res->content)->{Body}), "\n";
} else {
    print $res->status_line, $res->as_string, "\n";
}
$ perl sample_books_genre_search.pl 000

と実行すると、以下のような結果が得られます。引数の”000″はルートのジャンルIDです。これを”001″のようにすると、”本”のジャンルの子ジャンルが取れます。

$VAR1 = {
  'BooksGenreSearch' => {
    'parent' => [],
    'current' => [],
    'child' => [
      {
        'genreName' => '本',
        'genreId' => '001',
        'genreLevel' => 1
      },
      {
        'genreName' => 'CD',
        'genreId' => '002',
        'genreLevel' => 1
      },
      {
        'genreName' => 'DVD',
        'genreId' => '003',
        'genreLevel' => 1
      },
(以下省略)
};

Amazonと楽天の両方のAPIを見ていて思ったのですが、Amazonのカテゴリを表すBrowseNodeは、例えば”本”とかそういうカテゴリだけじゃなくて、”岩波書店”みたいな出版社にも適用されています。例えば、”岩波書店”にはBrowseNodeIdとして”516508″が割り振られていて、子ノードには”岩波文庫”や”岩波現代文庫”があり、「出版社別」みたいな切り口でも商品を分類することが可能です。

一方で楽天の場合は、商品一つに対してジャンルという純粋な一つのカテゴリしか設定されないようなデータ構造になっています。サイトを作る上では、様々な切り口で商品を分類できた方が集客がしやすいので、個人的には楽天ウェブサービスにもBrowseNodeみたいな概念を取り入れてもらいたいなぁと思いました。(リクエストはしました)

というわけであまりまとまってないですが、こうやってECサイトのAPIが利用できると個人でもECサイトが持てるので夢が広がっていいなぁと感じています。といってもアフィリエイトだったら利益はたかが知れているので、よっぽど頑張らないといけないと思いますが…

カテゴリー: Perl タグ:

PerlでAmazon Product Advertising APIのBrowseNodeLookupを行なう

2009 年 9 月 23 日 oinume コメントはありません

AmazonのProduct Advertising APIで、あるカテゴリの下にあるカテゴリ(BrowseNode)を取得するPerlスクリプトを書いてみました。最初はNet::Amazonを使っていたのですが、オブジェクトを大量に生成するためかとてつもなく重いのと、返ってくるオブジェクトの構成がよくわからなかったので、自前で処理してみるとさくっとできました。

#!/usr/bin/env perl
 
use strict;
use warnings;
use Encode qw(encode);
use LWP::UserAgent;
use URI::Amazon::APA;
use XML::Simple;
use YAML qw(Dump);
 
unless (@ARGV) {
    print STDERR "usage: $0 browse_node_id\n";
    exit 255;
}
 
my $uri = URI::Amazon::APA->new('http://ecs.amazonaws.jp/onca/xml');
my $browse_node_id = shift;
$uri->query_form(
    Service     => 'AWSECommerceService',
    Operation   => 'BrowseNodeLookup',
    SearchIndex => 'Books',
    BrowseNodeId => $browse_node_id,
);
$uri->sign(
    key    => 'key',
    secret => 'secret_key'
);
 
 
my $ua = LWP::UserAgent->new;
my $res = $ua->get($uri);
my $content = XMLin($res->content);
my $children = $content->{BrowseNodes}->{BrowseNode}->{Children}->{BrowseNode};
if ($res->is_success) {
    print encode('utf-8', Dump($children)), "\n";
} else {
    print $res->status_line, $res->as_string, "\n";
}
$ perl sample_browse_node.pl 465610

とすると下みたいな感じで下の階層のカテゴリを表示します。ちなみに465610は本のBrowseNodeIdです。Net::Amazon–、URI::Amazon::APA++ということで。

---
- BrowseNodeId: 466284
  Name: 文学・評論
- BrowseNodeId: 466288
  Name: 思想・社会・ノンフィクション
- BrowseNodeId: 571582
  Name: 人文・思想
- BrowseNodeId: 571584
  Name: 社会・政治
- BrowseNodeId: 492152
  Name: ノンフィクション
- BrowseNodeId: 466286
  Name: 歴史・地理
- BrowseNodeId: 466282
カテゴリー: Perl タグ: ,

YAPC::Asia 2009に行ってきました(9.10)

2009 年 9 月 18 日 oinume コメントはありません

2009/9/10,11に開催されたYAPC::Asia 2009に参加しました。今年はフレームワークやORM系のセッションがとても豪華で全部聞きたいなと思っていたので、迷うことなく有給を取って参加。というわけで殴り書きですがメモと感想を徒然に書いてみます。

PSGI – Perl Server Gateway Interface

スライド

tokuhiromさんとmiyagawaさんのコラボレーション。PSGIは仕様でPlackは実装。HTTP::Engineには仕様とAPIと実装が全て入っていたのでこれを分離しましたよ、というお話。YAPCの1週間前ぐらいから開発し始めていてすごい勢いで実装されているらしいです。PlackはいわゆるReference Implementationですが、かなり速いという話でした。Reference Implementationという用語を聞いて、JavaのServlet APIをなんとなく思い出しました。

シックスアパートフレームワーク

shigetaさん
スライド

Six ApartではMTフレームワーク, ArcheTypeの2種類のフレームワークがある。
MTではMTオブジェクトがData::ObjectDriverを継承している。Data::ObjectDriverはSix ApartのCTOの人が作っているORマッパ。memcachedによるwrite-throughキャッシュが実装されてたり、shardingもサポートされている。たしか2年前ぐらいのYAPCでセッションやってたと思います。

驚きだったのは、TypepadではHTML::Templateを使っているということ。普通はTTとか最近だったらText::MicroTemplateのような高機能なものを使うと思うのですが、ななぜあえてHTML::Templateなんでしょうか。っていうのを質問すれば良かったと今になって後悔。

API Design

sartak – Shawn M Mooreさん。Mooseのコミッター。
スライド

  • Moose
  • Path::Dispatcher
  • HTTP::Engine
  • Dist::Zilla
  • IM::Engine

今日はこれらのプロジェクトが持つクールなAPIの話をします。大事なのはテストをたくさん書くこと!なぜならテストを書けば使いやすいAPIかどうかわかる!あとはMooseなどの話。HTTP::Engineは新しいサーバのInterfaceが出てきても一行書き換えれば対応可能なところが素晴らしい、と言っていました。
英語だったので話の内容の半分も理解できなかったのが無念…

Modern Catalyst

hidekさん。最近DeNAに転職した? らしい。スライド

  • Catalyst 5.8について
  • Mooseベースになった
  • M,V,Cの名前空間がdepreatedになった
  • NEXTが…
  • Catalyst::PluginなnamespaceのプラグインをCPANにあげるとmstにおこられるw

他のセッションでも「Catalyst 5.8使ってます」という話をちらほら聞いたのですが、Mooseベースになったら速度が遅くなったりしてないのかな、というのが気になっています。

ark – framework inspired by Catalyst

KAYACのtypesterさん。スライド

  • KAYACでは大量に自社サービスを作っている。
  • Catalystでもいいんだけど、もうちょっとライトなWAFがよかったのでHTTP::Engineをベースに作った。
  • CGIモードでも割とサクサク動くようになってる。
  • CGIの場合はクラスはlazy loadingするように工夫
  • あとdispatch tableのキャッシュもしている
  • テンプレートはText::MicroTemplate::Extendedというものを使うのが推奨されている。もともとはMojo::Templateをokuさんが切り出したもので、それを拡張している。
  • Ark::Models – CLIスクリプトからでもModelを使える仕組み。あとlazy loadingをやったり。
  • Ark::Form – HTML::Shakanベース
  • KAYACのArkで作られたサービスの一部はなんとソースコードが公開されている!
  • いなめなヶ崎
  • im.kayac.com

Ark、Catalystとほぼ互換っていうのがいいなぁというのと、日本のモバイル対応版が早くリリースされないかな、って思いました。モバイル対応はもう必須になりつつあるような世の中なので、そのあたりのベストプラクティスを積み上げていってほしいなぁと。

優しいモダンなWAFの作り方

dannさん。スライド

  • モダンなWAFとは?
    • プラガブル – Plagger
    • サーバ抽象化 – PythonのWSGI
    • フルスタック – Rails
  • Angelos::PSGI::Engine
  • Plack::Requestを使ってる
  • HTTP::Routerを使ってる
  • シンプルなWAFなら2,3時間あれば作れちゃう!
  • 次、WAFの拡張部分の作り方(プラグイン)
  • コアは小さく
  • 拡張可能な箇所を限定(Controller, View, Middleware, Request, Response)
  • Hookポイントを明確にする
  • プラグインの種類は大きく分けると2種類
  • RequestやResponseのライフサイクルへのHook系
  • メソッドはやす系
  • 適切なデフォルトセットの提供することが重要
  • そうしないとUnicode化するためのTIPSが乱立したり、Inflate/Deflateするための(ry
  • HTTP::EngineやPlack、HTTP::RouterなどのモジュールのおかげでWAF作りがかつてないほど簡単になっている!

Arkの話も聞いてて思ったのですが、Sinatraみたいなレベルであれば本当に2,3時間で作れそうな気がしました。これからフレームワーク戦国時代の幕開けですね。そして懇親会でも直接dannさんに言ったのですが、Angelosを早くリリースしてほしいです… (切実)

Booking.com & Perl

Cristina Nunesさん(from リスボン,ポルトガル)。スライド

    Class::DBI(frozen version)
    HTML::Mason
    HTML::Template (forked version)

  • Perl 5.8.8
  • Class::DBI
  • HTML::Mason
  • HTML::Template(forked version)
  • なぜPerl? –> 簡単で速い
  • なぜHTML::Template? –> 簡単
  • なぜClass::DBI? –> 聞き取れず(一番聞きたかったのに)
  • Apache + mod_perl
  • MySQL
  • memcached
  • git
  • Jabber
  • 将来のゴール

    • Perl upgrade
    • Modules upgrade
    • Apache + mod_perl upgrade (to 2.x)
    • MySQL upgrade (to 5.1 or 5.4)
  • フロントエンドのWeb Server: 100台以上
  • MySQLサーバ: 100台以上
  • データセンターにあるサーバは700台以上
  • IT at Booking.com

    • Perl developers
    • Java developers
    • Network engineers
    • Sysadmins (社内SEみたいなものかな)
    • Web designers
  • 世界に25オフィスある
  • 1900人の従業員
  • 71000L hosts over 70 countries
  • 4500+ distribution partners
  • 24 languages available on website

Booking.comって初めて知ったのですが、ヨーロッパのホテルはかなり網羅されているという情報がIRCで流れてました。なんでいまだにClass::DBI使ってるんだろう、と思いましたが、mod_perlのバージョンも1.x系なので、やっぱりサーバの台数が多いとアップグレードも大変なのでしょうね。「Booking.comという会社は著名なPerl hackerを何人も抱えている会社なのです」という牧さんの補足がありました。

Key Value Store with O/R Mapper

yappoさん。スライド

  • Key Value StoreとO/R Mapperの合わせ技 –> Data::Model
  • Data::ModelはいわゆるO/R Mapper
    • DBI, memcached protocol, Perl hash, Perl code, Gearman
    • Q4Mにネイティブ対応
    • 透過キャッシュ
    • MixinによるSchemaクラスの拡張
    • ちょっとなういイテレータ
  • なんで既製品では駄目だったのか?
    • Class::DBI – DBICに移行する方向になってる。偉大なる先輩に感謝
    • DBIx::Class – 過去に使っていたがあまりいい思い出がなかった
    • Rose::DB, Jifty::DBI – 見る時間があまり取れず…
    • DBIx::Moco – ドキュメント少ない。実際にサービスで投入されているものと公開されているモジュールの差異が激しい
    • Data::ObjectDriver – Six Apart謹製。意外とテスト少ない&document少ない。ただしコードは大分参考にさせてもらった
    • DBIx::Skinny – 日本のPerl ORM専門家のもの。シンプルなスキーマに対して「生SQL書けます」はあまり魅力的じゃなかった。
  • 結局調べているうちにORM作成のポイントがわかってきたので自分で作ることにした
  • ORMはSchema, Iterator, Row, SQL, DBの5つのものがあればよい
  • Data::Modelのデモ(詳しくはスライドを参照)
  • TokyoCabinetをストレージとして使う場合、データを小さくした方がキャッシュにのったり色々嬉しいので、データは圧縮して小さくするべし。
  • Perl標準のStorableはデータ効率が悪いことで有名 –> 代わりにMessagePackを使用(これがすごいらしい)
  • KVSがストレージならALTER TABLEが必要なくなる。FriendFeedの例のようにすれば、スキーマなくても大丈夫
  • MessagePackがとにかくすごいらしい

まずスライドがFiciaだったのが驚きでした。なるほど、そういう使い方できるんですねー。途中のData::Modelのチュートリアルでは、その高機能さ(透過キャッシュやMasterSlave、column_sugar)に驚きました。自分でもオレオレORM作ってるのですが、相当レベル違うなと感激しましたです。その他、MessagePackがすごい使えそう、というのがよくわかりました。圧縮のアルゴリズムがカリカリ過ぎです。

simple or mapper DBIx::Skinny

nekokakさん。スライド

  • なぜ自分でORMapperを作ったか?
  • DBIx::Classが微妙…
    • 便利だけど発行されるSQLが微妙
    • パフォーマンスが出なかったりする
    • 生成されるオブジェクトがでかすぎるため重い
    • カスタマイズしようにもソースがでかすぎる
    • DBICで速度でない場合は生SQL書くことがあるが、Inflateとかしてくれない
  • 生SQL書いてinflate/deflateしてくれるライトなものでいいんじゃないか、というところにたどりついた
  • DBIx::Skinnyのデモ
  • relationshipは特に何もしない
  • コアは小さく、がモットーなので、拡張したい人はラッパーを書けばいい
  • 何人かの人に興味持ってるみたいなので、Skinnyみたいな方向性はありなのだなと思った。

ちょいと前にSkinnyのバグを見つけたのでメールでパッチ送ったりしていて、ちょうどYAPC当日にnekokakさんと直接お話させてもらう機会があったのですが、いやー非常に嬉しかったです。懇親会でもお話しさせてもらったのですが、やっぱり生SQL全然ありだよね、と思いました。もともと自分がSkinnyに興味を持ったのは、自分が3年前ぐらいに会社で作ったO/R Mapperと非常に設計思想が似ていて、「へー」と思ったのがきっかけです。(もちろんSkinnyの方がAPI的にも非常に洗練されているのですが…)

というわけで、自分もDBIx::Thinというのを作っているのですが、早く安定板をリリースしないと。とにかくエンジニアとしてはとても刺激になったセッションでした。

『Ficia』インフラとPerlにまつわるエトセトラ

hirose31さん@えとらぼ。スライド

  • Linux 2.6, Apache2, mod_perl 2.0
  • mod_perl 2のメモリ関連のチューニング
  • 推測するな計測するべし(ps, top)
  • fork(2) – Copy On Write
  • /proc/PID/smaps (kernel >= 2.6.14) – 共有領域: Shared_Clean + Shared_Dirty
  • いわゆる親プロセスと子プロセスの共有メモリ領域の話
  • id:naoyaさんの日記が詳しい
  • 使うモジュールは親プロセスで起動時に(startup.plなどで)ロードする –> 子プロセス独自のメモリ領域にロードしないので節約になる
  • Apache起動直後は共有率99%。時間が経つと共有率が40%ぐらいになり、プロセスのメモリ消費量が多くなる
  • 使用しているモジュールの一覧をどうやって取得するか?
  • Apache2::Status –> Loaded Modules で一覧を確認
  • あと親プロセスでモジュールをロードしておくと、コンパイル済みで即戦力になるのでオーバヘッドが少ないらしい
  • サイズがもりもり太っているモジュールを探す方法 – Apache2::Status + B::TerseSize
    。Memory Usageで一覧を確認
  • nagiosで少しでもswapしたらメールを飛ばすようにしている
  • 以降、httpd.confの話
  • StartServers != {Min,Max}SpareServers
  • 忙しい時はMaxに。ヒマになったらStartServersの数に戻る –> forkするのがむだ?だったら最初から全プロセス起動しておいた方がいい
  • /etc/init.d/httpd stop
  • stopしたのに新規リクエストが来ちゃう(ロードバランサーのヘルスチェック後とか)
  • start – 起動時からフルでプロセスを起動するので、start直後にリクエストが来ると負荷が高くなってしまう。一定時間おいてからロードバランサーに入れる必要がある。
  • ロードバランサーのヘルスチェックのURLを動的なものにしておき、フラグファイルがあったら200を返すようにするとか。
  • あとはmatrixの話

mod_perlのチューニングのような話は、最近はみんなFastCGIに移行しているのかあまり聞かないので、非常にためになりました。あと、StartServersで最初から一気にプロセス立ち上げておく技は昔考えたことあったのですが、LBのヘルスチェックとか面倒だなぁと思って挫折した経験があります。なるほど、ヘルスチェックのURLを動的にしてフラグファイルで管理っていうのは全然ありだなと思いました。というかRubyのpassengerとかはそんな感じの実装になってますね。

一日を通しての感想

おそらく初めて丸一日ぶっ通しでセッションを聴いたのですが、最後の方はやはり集中力がもたなくていいセッションでもあまりちゃんと聴けなかったのが残念です。ただ、エンジニアとしてのモチベーションは上がりまくりで、懇親会中も「早く家帰ってコーディングしたい」と実は思ってました。あと酔った勢いでDBIx::Skinnyのポスグレ対応とかしたのですが、バグとかテストを sfujiwara さんに面倒見てもらったようで、非常に恐縮でした…

個人的に非常に参考になったのは、Ark、Data::Model、DBIx::Skinny、Ficiaのインフラでした。WAF, ORMapper, インフラの話が聴けて大満足です。

カテゴリー: YAPC::Asia タグ: ,

YAPC::Asia 2009に行ってきました(9.11)

2009 年 9 月 11 日 oinume コメントはありません

すごい今更ですが、記憶が残っているうちに9.11のYAPC::Asiaのレポートをば。2日目も色々セッションに参加したのですが、特に記憶に残っている最初の2つだけ。

DeNA loves Perl

notoさん。スライド

  • DeNAはエンジニアは100人ぐらいで半分ぐらいはモバゲー
  • 今回のYAPCでも3人がセッションで発表している。(hidek, zigorou, matsuda)
  • 最初のbiddersはJava+Oracleだった
  • モバオクを川崎さんが作る時に初めてPerlをつかった
  • Perlは読みやすい、実行速度も速い
  • 最近はmyDNSのDNS RRの代わりにLVSを使うようになった
  • memcachedも使っている
  • MySQLのshardingもしている。モバゲーでは90個ぐらいに分割されている
  • mobamail
  • モバイルのメール配信 – キャリアの都合で接続がdenyされることがある。大量に送り続けるとdenyされる
  • キャリアのMXレコードは異様に少ない
    • docomo.ne.jp – 4IP
    • ezweb.ne.jp – 1IP
    • softbank.ne.jp – 1IP
  • キャリアのメールサーバが少ないから、送信側で送信先を分散できない
  • mobamail – Perlで実装したモバイルメール向けの配信サーバ。配信するだけなのでMTAじゃない(SMTP受ける方は実装してない)
  • コネクションを貼るところでIO::Selectを使っている
  • キャリアの制限の範囲内でなんとか最速で配信できるようにする。キャリアごとに細かい設定ができるように。
  • SIELLA Engine – より速い。さらに自分たちで設定しなくても楽。最近はこっちを使っている(ズコー)
  • (話は変わって)モバゲーのオープン化について
  • OpenSocial + Game API 法人に解放
  • 10/5 にフォーラム。来年1月以降に一般公開
  • DeNAのエンジニアのポリシー – ビジネスの成功にコミットすること
  • お金で解決しない。技術で「安く、早く」
  • ビジネスの成功を重視しているので、きれいな技術が二の次になっているのは否めない
  • 100人近くPerlエンジニアがいるのにCPANコミットがない
    • 他社の特許侵害のリスク(一部上場しているので目をつけられてしまう)
    • やりたい人がいたら推奨しようとしているが…
  • DeNAのPerlでの開発方針
    • 「一筆書き文化」:再利用せいや汎用性の設計に時間をかけるくらいならそういうことは考えずに書く方が速い
    • サービス単位の独自性・機動性重視=モジュールの共有なし
    • 割り切りの思想、逆転の発想、これでサービスを速くリリースしてきた面も
  • 今後の展望
    • 大きな開発チームでのポリシー
    • more test code
    • MobaSiFの次のバージョン
  • DeNAで一緒にコードを書きましょう!
    • as DeNA software engineer / architect
    • as developer of moba-ga town
    • as CPAN author

携帯向けのメール配信でSIELLA Engineを使っているのが驚きでした。ああいうモバイル向けのパッケージ製品って他にもKlabのアクセルメールとか良さそうなのいっぱいあるし、やっぱり餅は餅屋にって感じなのでしょうか。

モバゲーのAPIがオープン化されるということは、PC向けにFlashでゲームも作れるのかな?というのが気になりました。現状モバゲーのPCサイトってモバイル版のはりぼてみたいなものなので、これを機にPCサイトも盛り上がるといいのかなぁと。

endeworksでのWeb Appの作り方

33rpmさん(船木太郎さん)。スライド

  • 牧さんが代表の会社です。
  • 特別なことはやっていない
  • 開発サーバは用意していない(個人のMac上で開発)
  • Test::FITesque が最近の流行り(読み方よくわからない)
  • ディプロイ – git pullするだけ。ディプロイツールといったものは使用していない
  • Apache+FCGI – daemontoolsでFCGIのプロセスを管理
  • Catalystを使用
  • Mooseを使用 – Catalyst 5.8をプロダクション環境で使用
  • APIモジュール
  • CatalystのModelを使用しない
  • CatalystのModelは当たり前だけどCatalyst依存
  • ModelはWebという枠組みの外、たとえばCLIやWorkerからも呼び出したいことが多い
  • MyApp::API::* という名前空間
    • 中身はORM+アプリケーションロジック
    • キャッシングのロジックもここ
  • DIコンテナは? – アプリケーション全体で共有されるインスタンスはRegistryというモジュールに格納
  • Registry – メモリ上のKVSに保存するだけのsingleton object
  • Formの作成はHTML::FormFuを使用
    • 生成されるHTMLに不満
    • HTML::FormFuのValidatorはとてもよくできているので、レンダリングはさせないでValidatorだけ使うというのが最近の流行
  • pixis(フレームワーク)の説明(githubで公開されている)
    • WebサービスやSNSでありがちなメッセージ管理などのソーシャル機能をまとめたフレームワーク
    • Catalyst 5.8依存
    • 依存モジュールが多い
カテゴリー: YAPC::Asia タグ: ,
Pages: << 1 2 3 4 5 6 7 8 ...18 19 20 >>