へぼい日記
#ISUCON2 で特別賞を頂いて来ました
- 2012/11/4 日曜日 14:08:29
- perl
というわけで前回に引き続き山形組として参加してきました。
まとめブログはこちら
結果は、スコア18万切りに最初に到達すると頂ける特別賞を16時ごろ10万ちょうどぐらいのスコア(スコアは低いほうが優秀)で頂いたものの、その直後に藤原組さんにさくっと8万あたりのスコアで抜かれ、こちらも9万台のベストスコアはだしたものの、最終結果は10万あたりで、藤原組さんは8万台で2位で終了。
スコア的には僅差だったので正直かなり悔しいですが、藤原組さんは「実運用に突っ込んでも運用が破綻しない状態」を維持されていたようで、うちはかなりチート手法でしたのでこれはもう完敗ですね。次があったら正攻法で戦えるように経験値を上げて望みたいなと思いました。
やったこと
アプリ全書き換え
1fileなPSGI
https://gist.github.com/4006644
feersum(1プロセスマルチスレッド)
データはすべてオンメモリ
スレッド間でシェア
部分的なhtmlのキャッシュ
永続化はテキストファイルへjsonで追記
リバースプロキシだけでアプリも立ち上げ
つまり動いてたのは一台だけ
DBサーバがスペックよかったのでそっちでアプリうごかせばよかったかも。
リバースプロキシをnginxに
やれなかったこと
永続化の遅延
リバースプロキシでstatic serve
なぜかやるとFAILした
これがkazeburoさんの罠とざわつく
nginx -> feersum間をkeepalive
nginx embedded perl
Plack::Handler::Nginx
上記のFAIL問題で焦ってて時間なくなってできなかった
TIME_WAIT対策
reuseつかったらFAILした
他の問題かも
コンテスト中の流れ
前回の感想ブログエントリに書いた通り一人Isucon1をやっていたときに、nginx embedded perlでデータはすべてオンメモリが最速という結論を得ていたので、その方法がとれるようであれば今回もやろうと事前に考えていました。
今回は最初にぱっと構成をみたときにstockデータがそれなりに大きかったのでこれはオンメモリは無理か?と思ったもののvariationごとの64*64の単純なデータ構造だったのでこれは計算でいける、とオンメモリ化でいく決断を開始一時間後ぐらいにする。
であれば用意されているアプリとはまったく考え方が違うので、一から実装のほうが早いと判断し、がりがりとコードを書き始める。で、途中お昼食べたりしつつ4時間ほどでできたのがこれ。今回の参加者中キータイプ数なら間違いなく一位だったと思う。KINESIS最高!作り方としては既存アプリのコードはなるべく見ないでブラウザから外部仕様の動作確認をしつつ移植という感じ。
オンメモリデータの一枚psgiなので手元の環境のplackupのみで簡単に動作確認できるというのは一つの強みだったとおもう。
で、それをデプロイしていくつかの移植ミスによるFAILをクリアしたところで10万スコアがでて特別賞。
その後nginx embeddedに進むためにもstatic serveをnginxでしたところなぜかFAIL。
このあたりから完全に迷走し、いろんなことに手をだし(nginxの最新バージョンを試したりtime_wait問題の解決を図ったり)何が原因でFAILしてるのかも見失う状態になり肝心のnginx embedded perlの作業に入れず、とりあえずFAILを解消しよう!といろんなことをrollbackしてなんとか完走するようになったところでタイムアップ。
感想
普段負荷を要因としたスケールアウトを必要とするような仕事をほとんどしておらず、安易なスケールアウト戦略に疑問をもっているというのもあり、世間で王道とされていることに対するアンチテーゼとして、この実装で優勝するということを密かに狙っていました。
会場では「業務には役に立たないチートです」と言いましたし王道な藤原組さんに結局負けてるわけですが、「なぜスケールアウトするのか」という点を考えるきっかけになってもらえたらいいなぁと思っています。
インフラチームが4台用意してくれてるんだからとりあえず4台使って分散してみるか~という安易な考えではなく、ボトルネックの解消や冗長性のためなど具体的な測定結果や理由によりスケールアウトするべきなんだろうなぁと。
まあ負け犬の遠吠えですが!
主催されたNHNのスタッフのみなさん、こんなに楽しいイベントを開催していただき、本当にありがとうございました!
YAPC::Asia Tokyo 2012に参加してきました
- 2012/9/30 日曜日 20:13:06
- perl
参加してきました。YAPC::Asia Tokyo 2012。
初発表してきました
Tengにpull requestをよく送っていたからか、nekokakさんにやりませんかとIRCで声をかけて頂いて、やりますーと軽く答えて参加申し込みをしたはいいものの、ちゃんとした話ができるのか不安でしかたがなく、直前は緊張で吐きそうになるなどしつつ、発表者席に向かったところ目の前にnekokakさんが陣取っており(その場ではじめましてのご挨拶(!))、プレッシャーでクラクラしながらも、なんとか発表させていただきました。
反省点は多々ありますが、なんとか最後まで喋りきることはできたので一応満足はしています。今後は自分のプロダクトでの発表や、40分枠で喋れるような濃い発表ができるように日々意識して活動していこうと気持ちを新たにしました。
プレゼン資料公開しておきます。
追記: 2012/10/6 動画アップロードされたみたいです。
聞いてきた
もろもろのお仕事の事情により、参加は発表日の午後から。(発表日午前いけなかったのは起きれなかっただけだけど!)
Perl 今昔物語
僕はYAPCは2007年の津田塾以降の参加。ここ数年(PSGI/Plack以降って感じなのかな)新しいPerlのプロダクトとかでてきてないよねーという話はまあそうなのかもなと。
他の言語でも最近は落ち着いてるんじゃない、という話もあったけど印象としてRuby界隈は活発に見えるし、実際RubyGemsの数がCPANモジュール数を超えている(count方法に異議はあるとのこと)という話をその後のLTでcharsbarさんがされていましたね。
10 more things to be ripped off
スライドはこちらのようです
裏番組のPerl と SQL のいろいろは自分の発表と内容も関係ありそうだし、場合によっては発表中で触れるためにも見ておきたかったんですが、miyagawaさんのこのトークはmiyagawaさんだからってのを差し引いても、内容的にやっぱりどうしても見ておきたかったので。
bundler to Cartonの話は今一番興味がある話で(これの話とかcpanfileの100%実装とか)、未実装の部分を開発してくれる人歓迎というようなことをおっしゃっていたので一念発起してみるつもりです。他のプロダクトも興味あるものがいくつかあったので要チェックでしたね。
Perlハッカーは息をするようにCPANモジュールを書く。
まとめが、githubに眠っているモジュールをドキュメントをちゃんとかいてCPANにアップしよう!というような話だったので、勢い余って質問で「githubに眠っているPath-AttrRouterはいつCPANにアップされますか?」という嫌がらせのような質問をしてしまい、流れでドキュメントを書きますと宣言をしてしまいました…。や、やりますよ!そ、そのうち!
— 発表が近づきおぼつかない足取りで外をふらふらとうろつくなど記憶が曖昧な時間帯 —
Lightning Talks Day 2
あいかわらずみなさんおもしろい。正直あそこには一生立てる気がしないです。あ、途中karupaneruraさんがTengを絡めた話をされてましたが、自分の理解力が足りず内容が半分も理解できなかったのでスライドの公開を待ちます!
How Perl Changed My Life
やっぱりmiyagawaさんには影響されちゃいますよねー、あるあるという感じでした。
また来年?
また来年も開催されるのかはやはり明言されなかったみたいですが、あるときに備えておきます!
こんなに素晴らしいイベントを運営されているボランティアスタッフの皆様、本当にお疲れ様でした!
ところで、このブログはすっかりイベント参加報告ブログと化していますが、最近はheboi blogのほうでカジュアルに書いています。
YAPC::Asia Tokyo 2011に参加してきました
- 2011/10/16 日曜日 19:36:39
- perl
YAPC::Asia Tokyo 2011に参加してきました。
ブログ書くまでがYAPCというわけで印象にのこったセッションを中心に参加報告を。
前夜祭
myfinderさんの「サービス運用者のための継続的監視」はさすが日本で1番目か2番目か3番目のSNSの運用をされてるだけあってさすがという感じでした。自分は小規模システムばかりやっていて開発者も運用についてかなりコミットしなきゃいけない状況で働いているのですが、ここまできちんとできてないなーと痛感。さっそく監視項目をどんどん増やしていこうと思いました。
会場外のプチ懇親会的なものでは、ほぼボッチでしたが夏菜子推しTを装備していたsugyanさんと初めて挨拶させていただくなど。
一日目
寝坊&体調不良で昼から参加。Jesse Vincentさんの「Perl 5.16 and beyond」とmalaさんの「Webアプリケーション高速化」が聞けなかったのが残念。動画とか公開されるのかな。
onishiさんの「新はてなダイアリーの裏側」では、はてなダイアリーが今秋Hatena Blogになることが発表されたりしていて、ユーザ毎サブドメイン運用でjavascript解禁なんて話があってセキュリティ対策とかどーなのかなーと興味深かったです。二日目のcho45さんの「ぼくがかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく 」でそこらへんの話も詳しくされたぽいのですが裏セッションを聞いてて見れなかったです。
徳丸さんの「Webアプリでパスワード保護はどこまでやればいいか」ではレインボーテーブルの原理を丁寧に説明されていて(徳丸本にも書いてあるのですが読み飛ばしてしまっていたので)、なるほどなーと思ったり、高速化するGPUの脅威に対抗するためにサービス側でもGPUを使ってハッシュ生成(ストレッチング回数を増やす)するという対策を示しておられたのが印象的でした。
makamakaさんの「Perl Mongerなりきりカードゲームの考案と実践」はとにかく面白すぎましたw会場のウケをとった回数だけならきっとベストスピーカー賞なんじゃないでしょうか。
懇親会ではほぼボッチでしたが、miyagawaさんに僕のビール持って行っちゃってませんかという(濡れ衣の)難癖をつけるなどしました。(わざとじゃありません。すみません)
二日目
若干遅刻気味だったので大岡山駅からダッシュで会場に向かい、ぎりぎりkazuhoさんの「続 Unix Programming with Perl」の開始に間に合いました。昨年の発表もそうでしたが正しくプログラミングするとはどういうことなのかということを徹底的に意識されている感じで非常に勉強になりました。
Ricardo Signes(rjbs)さんの「闇のEメール伝説」はEmail::モジュールの話をするのかなーと思って行ってみたら、SMTPやMIMEのRFCにまつわるメールのカオス状況をおもしろおかしく発表されるという感じでした。英語は正直ほぼ聞き取れてなかったのですがスライドを見るとだいたいは把握できたし、メールアドレスの正規表現をやってたときにRFCがupdateされて古いRFCがobsoleteになっても新しいRFC自体にobsなsyntaxが残ってたりしてカオスってるのを把握してたのでそうそうそうだよねーという感じで楽しく聞けました。
スイーツエリアで開催されたmotemenさんの「Teto でニコニコ音声ストリーミング 」は便利そうだし、技術的にも面白そうなので是非使ってみてコードも読みたいなーと思いました。
勝手に後夜祭では、ほぼボッチは回避しつついろんな方と話すことができました。途中YappoさんとEmail::Senderの非Moose化てどうなんでしょうねーという話をしていたらcharsbarさんに折角本人がいるんだから直接いいなよとrjbsさんの前に連れていかれcharsbarさんに通訳をしてもらいながらお話を聞くことができました。RoleがMooseとMouseで完全に共通化されてないからAny::Mooseは使えないよねーという話だと理解したのですが正直完全には理解できず。英語ェ…。周りに集まってきたPerlHackerの面々が直接英語で議論しているのを目の当たりにしてほんと英語どうにかしないと駄目だなと再度感じた次第。charsbarさんその節はありがとうございました。力不足で大して議論を深める役には立てませんでしたが貴重な経験になりました。
というわけで三日間非常に楽しめました。
牧さん櫛井さんをはじめJPAのみなさん、ボランティアスタッフのみなさん、スピーカーのみなさん、お疲れ様でした&ありがとうございました。
来年はスピーカーとして若干でも貢献したいとおもいます!
ISUCONに参加してきました
- 2011/8/30 火曜日 3:18:58
- perl
なんでもありのWebアプリケーション高速化バトル、#isuconに山形組として参加してきました。
結果はみなさんご存知の通り、藤原組さんの圧勝という感じになりました。
自分はというと、DBボトルネックの解消までは藤原組さんとほぼ同じ手法で解決して、4700req/minあたりのbest scoreを出した後には有効なチューニングが行えずにnginx導入の罠にひっかかって200req/minとかになってしまって泣きながらapacheに戻したりしつつ、最後はサイドバーのcacheをmmapにいれる作業をしていたらバグでfailするようになってしまってぎりぎりでDBのボトルネック解消直後にロールバックして、10000req/3minくらいがたしか最終スコアだったと思います。failしたチームを除けば下から数えたほうが早い感じになってかなり悔しい結果でした。
DBボトルネック解消直後にappサーバを一つにしぼったところたいして結果は変わらず、ああたかが10並列だしサーバ分散するほうが無駄なのかなとリバースプロキシでplackで直接80番ポートをlistenするとどうなるかなーと思ったりもしていたのですが、debianでdaemontools慣れしていた自分はceontosでsupervisordという構成にひるんでしまってそこまで踏み込めなかったので、帰ってきてからPSGI単体のアプリでどこまでチューニングできるかってのをやってみました。
で、できたのがhttps://gist.github.com/1178857これです。Feersumで動かしてあげると、自分の環境で96550req/minのベストスコアがでました。一応永続化もしているので(デーモン化の設定さえすれば)再起動後も有効な、ISUCONレギュレーション完全対応なPSGIアプリになっています。ISUCONアプリの全体像を簡単に見通したい方にもオヌヌメです。といってもこのやりかたはたかが10並列でたかが3分間のアクセス(とpost数)とわかっているからできる構成なので実際の運用にそのまま生かせるような内容にはなっていませんので、そこのところご注意くださいです。
こんなわくわくするイベントを開催してくださったlivedoorの担当者の皆様ありがとうございました!
追記: その後nginxとも組み合わせてやってみたところ(psgiもこんなかんじに修正して)

までいきました。nginxでは静的ファイルをserveして、keepalive,gzipオフ。
追記: nginx embeded perlで242686req/minでました。https://gist.github.com/1181564
nginx +proxy cacheでexpireしないようにして試すと、(当然FAILするけど)fetchesが30万前後だったのでまぁここらが自分的には限界
DBD::mysql 4.020がリリースされました
DBD::mysqlの4.020が昨日リリースされました。
このリリースにはmysql_server_prepare=1を使っている場合のバグの修正が5件ほど含まれています。(ChangeLog)
DBD::mysql で mysql_server_prepare=1 のとき TEXT 型の欄が自動 utf8::decode されなくなる
こちらのブログで指摘されていた件を直してパッチを送ろうと思っておもむろにmysql_server_prepare=1の状態でDBD::mysqlのテストを実行したら失敗しまくったため、もう駄目かもしれないと思ったのですが、何故かmysql_server_prepareと心中する腹をくくり一応すべてのテストを通すようにパッチを送りまくってみたところ取り込まれたという感じになりました。(リリース後に2つほどさらにpull reqしていますが…。)
TEXT型がdecodeされない件はユーザ側で回避できない話ではないんだと思いますが、LONGBLOBで4GBのメモリをアロケートしようとする件はDB構成によっては回避のしようもなく、mysql_server_prepare=1はほとんど使われてないんだなぁという印象を持ちました。
一応改めて整理しておくと、mysqlのサーバーサイドのPrepared Statementは以前はクエリキャッシュがされないというかなり致命的なデメリットがありましたがバージョン5.1.17以降でC API等から利用されるバイナリプロトコルではキャッシュされるようになり、また5.1.22以降からはテキストプロトコル上でのPREPARE, EXECUTEでもキャッシュされるようになっています。(詳細はクエリキャッシュの動作を参照してください。)
mysqlのPrepared Statementはbind値を展開した後のクエリの結果をキャッシュしてくれるいわゆるQueryCacheのみの対応となっています。パラメータ値に依存しない実行計画をキャッシュしてくれるわけでは無いのでメリットは薄いと思われる部分はあるとは思うのですが、通信データが大きい場合には速いというメリットも持っています。(今回のDBD::mysqlのバグはそのメリットを享受するべきLONGBLOBがほぼ動かないというひどいものではありましたが)
memory leakのような現象が起きるという中の人の指摘もあったりしますが、これはステートメントハンドルやコネクションの管理をクライアント側できちんと行えば問題ないと思っていたりもします。(大規模環境でどうなのかというわれるとちょっとどうなのかなと思わなくもないですが)
というわけで、やはりまあ積極的に利用を勧める理由も無いのですが、積極的に回避する理由も無いとも思ってますので是非使えるかたは使ってみてください。で、DBD::mysql的にもMySQL本体的にも枯れてくれるとうれしいなと思ってます。
Gearmanのはまりどころ
- 2011/1/22 土曜日 21:19:36
- perl
最近Gearmanに入門しているのですが、いろいろとはまったのでメモ。
$worker->workは”Do one job”ではなくDo job loop
$worker->work while 1;
みたいなサンプルが書いてあったり
Gearman::Job->work(%opts) Do one job and returns (no value returned). You can pass "on_start" "on_complete" and "on_fail" callbacks in %opts.
って書いてあるのですが(しかもこれは、Gearman::JobではなくてGearman::Workerだし、、、)
workはオプション無しで呼ばれた場合はwhile 1なんかなくてもloopします。
work_once的な動きにしたいのであれば
$worker->work(stop_if => sub { 1 });
とすればいいです。stop_ifをmax_requests_per_child的な動きにしたい場合はkazeburoさんのgearman-starter.plを参考にするといいです。
ちなみにこれは作者にメールでパッチも送ったりもしたのですがこのRTが同じ内容。1年半ぐらい放置みたいなので直る気配なし。
Gearman::Client->job_serversはArrayRefを受け取れるけど、Gearman::Worker->job_serversは受け取れない
結構はまりました。
my $clinet = Gearman::Clinet->new; $client->job_servers(['127.0.0.1']);
はokだけど
my $worker = Gearman::Worker->new; $worker->job_servers(['127.0.0.1']);
は駄目。正しくは
my $worker = Gearman::Worker->new;
$worker->job_servers('127.0.0.1');
としなければならない。これもRTにあがってますね。
Gearman::Workerはfork safeじゃないんでfork後生成
まぁDBIのdbhとかと一緒ですね。いくつかのネット上の例でParallel::Preforkなんかと組み合わせて使う時に
親プロセスで$worker作って共有している例注1があったのですが、ちゃんとやるなら子供で生成すること。
一見普通に動いちゃうのですが通信がまざって変になるかもしれないです。
まとめ
あたらしくCPANモジュールを使い出す時にはPODと共にRTも一緒に見ておくとよい。
注1
ここの11pとかここ(もう直ってる)とか。ちなみにkazuhoさんの書いたものだと去年のadvent calendarのWriting a prefork server / daemon using Parallel::Preforkは子供でworker生成してます。この記事は、graceful shutdownやSIGHUPによるconfig reloadへの示唆が含まれているので必見ですです
X-Content-Type-Options: nosniffのつけ方
- 2011/1/6 木曜日 12:49:29
- security
Apache
mod_headersでできます
Header set X-Content-Type-Options nosniff
Nginx
add_header X-Content-Type-Options nosniff;
但し、上記だとproxyなんかで既にX-Content-Type-Options: nosniff;が付いていると
X-Content-Type-Options: nosniff, nosniff
のようなヘッダになってしまう。問題ないかもしれないが気になる場合はNginxHttpHeadersMoreModuleを使って
more_set_headers 'X-Content-Type-Options: nosniff';
とすると良いのかも。
Plack
Plack::Middleware::Headerを使うと簡単です。
enable 'Header', set => ['X-Content-Type-Options' => 'nosniff'];
参考: X-Content-Type-Options: nosniff つかわないやつは死ねばいいのに!
日本の休日をPerlから求める
- 2010/11/15 月曜日 18:11:18
- perl
日本の休日には「国民の祝日」と「振替休日」と「国民の休日」ってのがあるのですがそれをPerlから求めるにはどうしたらいいんだという話。
#perl-casualでたずねたところいろいろと方法を教えてもらいました。
定番ネタだし、それ三週目といわれたりしたのでまとめてみますたという流れ。
そもそも休日というのは法律で決められるものなので、改正もあり最近だと2005年に改正があったりしています。
また、「国民の祝日」の中には「春分の日」や「秋分の日」のように翌年分を2月に官報で発表なんてものもあったりします。
やっかいですね。
CPANモジュールを使う
Calendar::Japanese::Holiday
最終更新日が2007年なようですが
use Calendar::Japanese::Holiday; say isHoliday(2011, 3, 21); say isHoliday(2011, 9, 23);
こんな感じで未来の秋分・春分の日も計算で求められているのでそれなりに信頼感はあるかと思います。
ただし、「振替休日」に関しては下記のように第三引数に1をいれないと求めてくれないので注意。
use Calendar::Japanese::Holiday; say isHoliday(2009, 5, 6); # これだと駄目 say isHoliday(2009, 5, 6, 1); # これならOK
DateTime::Holiday::Japanese
CPANモジュールではないですが、coderepos上にfbisさん作のモジュールもあがっています。
use DateTime::Holiday::Japanese qw/is_holiday/; say is_holiday(year => 2011, month => 3, day => 21); say is_holiday(year => 2011, month => 9, day => 23);
Calendar::Japanese::Holidayと同様に更新は2007年からされていないようですが秋分春分の日は計算で出しています。
今日2009-2011のテストデータを追加してパスするのは確認しています。coderepos上にあるので法律変わったら誰かが更新してくれるんじゃないかという期待感あり。DateTime依存。
ネット経由で情報を定期的にとってくる
Google Calendar Data API
japanese@holiday.calendar.google.com
=> 「振替休日」「国民の休日」には非対応(「国民の祝日」カレンダーだからそれが正しいんだよ派)
outid3el0qkcrsuf89fltf7a4qbacgt9@import.calendar.google.com
=> 「振替休日」「国民の休日」にも対応。使えそう
https://www.mozilla.org/projects/calendar/holidays.htmlのJapan Holidaysと同じデータぽいのかな。
政府
「国民の祝日」についてが一番信頼できそうなネット上の情報な気もするが、別にこのページを維持すること自体を法律で定めているわけでもないし今年と来年のデータしかないのでそこまで使えるってわけでもない。「振替休日」と「国民の休日」については例だけなので将来的にどう表示されるのかも判然としない。
目視確認なら法律と官報を確認するに次いで信頼性はあるかと。
休日DBを独自に作成して運用者がメンテ
最強
まとめ
CPANモジュールの”その時点での法律計算”系は手軽さはあるが、今後の法改正を見越すと若干難ありか。
モジュール自体が毎年来年分のテストを追加してリリースされることが保障されていて、
使う側も毎年保守ができるのであれば特に問題はなさそう。
さらにモジュール自体もgithubなんかで複数人で保守されているといいなという話。
API系は信頼できるものを政府が出してくれるとうれしいなーというところ。
XslateはSyntaxを変えても基本的には実運用上の速度は変わらない
- 2010/8/13 金曜日 19:54:00
- perl
TTの158倍速いというxslateですが、このベンチマークはSyntax::Kolonを使っています。
TT互換なSyntaxであるところの、Syntax::TTerseを使うとどうなるのかなということでhttp://github.com/nihen/p5-Text-Xslate/tree/add_tterse_benchのbenchmark/x-rich-enc.plとbenchmark/x-poor-env.plにTTerseも追加してみました。
以下結果
%perl benchmark/x-rich-env.pl
Perl/5.12.1 i686-linux
Text::Xslate/0.1056
Text::MicroTemplate/0.15
Text::MicroTemplate::Extended/0.11
Template/2.22
Text::ClearSilver/0.10.5.4
HTML::Template::Pro/0.9502
1..5
ok 1 - TTerse: Text::Xslate::Syntax::TTerse
ok 2 - TT: Template-Toolkit
ok 3 - MT: Text::MicroTemplate
ok 4 - TCS: Text::ClearSilver
ok 5 - HTP: HTML::Template::Pro
Benchmarks with 'include' (datasize=100)
Rate TT MT TCS HTP Xslate TTerse
TT 78.6/s -- -69% -94% -95% -99% -99%
MT 257/s 227% -- -82% -84% -98% -98%
TCS 1412/s 1697% 450% -- -11% -89% -89%
HTP 1586/s 1918% 517% 12% -- -88% -88%
Xslate 13241/s 16752% 5054% 838% 735% -- -1%
TTerse 13397/s 16951% 5115% 849% 745% 1% --
%perl benchmark/x-poor-env.pl
Perl/5.12.1 i686-linux
Text::Xslate/0.1056
Template/2.22
HTML::Template/2.9
Text::MicroTemplate/0.15
Text::MicroTemplate::Extended/0.11
1..4
ok 1 - TTerse: Text::Xslate::Syntax::TTerse
ok 2 - TT: Template-Toolkit
ok 3 - MT: Text::MicroTemplate
ok 4 - HT: HTML::Template
Benchmarks with 'include' (datasize=100)
Rate TT TTerse Xslate HT MT
TT 49.5/s -- -27% -28% -61% -80%
TTerse 67.9/s 37% -- -1% -47% -73%
Xslate 68.5/s 38% 1% -- -46% -73%
HT 127/s 157% 88% 86% -- -50%
MT 253/s 411% 273% 269% 99% --
このように誤差の範囲ぐらいの差しか無く同様に速い。
これはなぜかというと、Xslateは様々なSyntaxで書かれたテンプレートを共通の中間コードにコンパイルし、それをキャッシュしているためその中間コードはほぼ同一のものになるからです。
一応そのコンパイル部分には差が現れるが、ファイルキャッシュもできない環境というのはほぼありえないので実運用上、速度の差は無いと言ってよいとおもわれる。というわけでTT使ってる人は安心してTTerseに移行してみるといいと思うです。(互換性がどの程度あるのかは使ってないから知らないけど!)
ちなみにコンパイル部分のみのベンチマーク
% perl author/bench_compile.pl
Parser: Kolon v.s. TTerse
Rate tterse kolon
tterse 80.1/s -- -42%
kolon 139/s 74% --
Path::AttrRouterにHTTPメソッド制限できる機能を追加してみた
- 2010/7/10 土曜日 23:53:26
- perl
Path::AttrRouterというtypesterさんが開発されているdispatcherがあって、Catalyst-likeなControllerのattributeを拾ってきてルーティングテーブルを作成してくれるのが便利で使っています。
で、HTTPメソッドを考慮したルーティングを行ってくれる機能が欲しかったので追加してみました。
method_supportブランチとしてforkしてgithubにあげてあります。
使い方はこんな感じです。
use Path::AttrRouter;
{
package MyController;
use base 'Path::AttrRouter::Controller';
sub index :Path { print "index\n" }
sub post :Path Method('POST') { print "post\n" }
}
my $router = Path::AttrRouter->new( search_path => 'MyController' );
my $m;
$m = $router->match('/', 'GET');
$m->dispatch; # index
$m = $router->match('/', 'POST');
$m->dispatch; # post
Methodが指定されなかったsubroutineはGET, HEADがデフォルトになるようになってます。
一応後方互換性は考慮してあり、$router->matchの第二引数が空の場合は
どのメソッドでもマッチするようになっています。
本家にとりこまれればうれしいけれど取り込まれなければ別distとして継承使って作り直すかもです。
ところで、諸事情により前職を退職していまして、ブログURLを移転しています。
RSSリーダーに登録されていた方等は再度登録お願い致しますです。
一応302飛ばすようにしてはあるんですが、RSSリーダーって自動的にそこらへん追跡してくれないんすかね。
追記(2010-07-11 17:17)
http://twitter.com/#!/typester/status/18255875606
とのことです。確かにPath::名前スペースなのでHTTPメソッドに依存するのは筋悪でした。
HTTP::AttrRouterとかで作ってみようかなーと考え中。
- 検索
- フィード
- メタ情報