D-7 <altijd in beweging>

Day to day life of a Perl/Go/C/C++/whatever hacker. May include anything from tech, food, and family.

2013年03月

cartonを使ってアプリケーションの依存関係を解決する際にちょっとはまったのでメモ。

複数のPerlがインストールされている環境、具体的には/usr/local/bin/perlが過去の遺産の5.8.8で、どこか新しいところに /path/to/perl-5.16.3/bin/perl とかをインストールしている環境で、新しい方のperlにcartonを入れて実行したら実行時にエラーになった。

エラーログを よく見るとモジュール読み込みに失敗していて、なぜか参照パスが/usr/local 以下とかになってる。

なんでやー、と思っているとどうもcartonを実行した際に以下のように絶対パスで実行していて:
/path/to/perl-5.16.3/bin/carton exec -- ....
はて、と考えると/usr/local/bin/cpanmが存在していて、どうもそれを使っているくさい。/path/to/perl-5.16.3/bin にはパスを通してなかったので、そこで取り違えが起きたということみたい。

/usr/local/bin/cpanmを消せばいいんだけど、なんかあとで言われるのも嫌なので、その辺りも含めて色々やるラッパースクリプトからcartonを呼び出す事にして、ざっくり以下のようにしておいた

local $ENV{PATH} = join ":", perl_binpaths(), $ENV{PATH};
exec("carton", ... ) 
 perl_binpath() は こんな感じ

use Config ();
sub perl_binpaths {
my %hash = map {
($Config::Config{$_} => 1)
} qw(installbin installscript installsitebin installsitescript);
return keys %hash;
}

まぁここまでやらんで、普通に PATH=/path/to/perl-5.16.3/bin:$PATH でもいいとは思う。癖です。 
    このエントリーをはてなブックマークに追加 mixiチェック

いつもは違うところで花見散歩をしているんだけど、今年は子連れとか諸々考えた結果、目黒川に行くことにした。ついては、日中や夜だと人が多そうなので朝行くことにして、その前に腹ごしらえをしようということで午前七時すぎに代官山TSUTAYAの敷地内にある ivy placeで朝食。

「ベイクドエッグとスモークベーコンのピペラード」と「フライドエッグ、スモークサーモンと季節野菜のハッシュ」を頼んだ。写真はピペラード。



「どうせシャレオツなだけでたいしたことないんだろうなー」とかちょっとなめてたけど、 これ結構うまいやないか!自分はハッシュのほうを頼んで食べたんだけど、これはなかなかよい。まぁネックは値段だけだけど、こういうところで朝食を食べる時ってのはそういうつもりの時なので特に問題になるほどじゃない。

子供にご飯を 食べさせながら慌てて食べたこともあったので夫婦で「ちょっとだけ物足りないかな・・・」といいつつ店を出たのだけど、時計を見たら8時過ぎ。は!この時間だったらメゾンイチがすでに開店してる!と気づき、ちょっとだけ代官山駅のほうに戻ってキッシュを購入して、目黒川のほうへ向かって散歩開始。

桜は満開でキレイー



目黒川では桜を楽しみつつてくてく。途中ちょっと腰掛けられるところがあったのでそこでキッシュを夫婦でわけて食べた。実はイチのキッシュを食べるのは初めてだったんだけど・・・うまいやないかあああ!くぅ、濃厚だ!とろとろだ!ちょうどいい塩加減だ!うまい!


あとは家用にリンゴとクルミのパンも買って帰ったけどうまかった。イチも結構お高めだけど、味は確実だな。

その後はずーっと歩いて目黒川の終わりまで。朝8時台で人はまだ少なかったし、いいお花見だった。ivy placeもイチもおすすめだよ!
    このエントリーをはてなブックマークに追加 mixiチェック

うーん、この本は「未完」。回収してない伏線がたくさんあるし、なにより作者が「これ以上書くと本の値段があがるからと言われて書けなかった」的な事をあとがきに書いている。現代と江戸時代をいったりきたりするのはなかなか興味ぶかかったけど、伏線が回収できてないので深みが全然でてこない・・・続きがあるなら読みたいけど、単体としては微妙。
    このエントリーをはてなブックマークに追加 mixiチェック

珍しくスパイものなんて読んでみた。主人公はさえないロシア史研究家で大学講師の男性。あるとくダネを追っていた知り合いが亡くなった時に諸事情によりそのあとを継ぎ同じネタを追う事にすると、突然イギリスやロシアの諜報部に目をつけられて・・・というスパイ小説的には多分割と王道なもの。

すごく目新しいところは特にないきはするけど、なかなか巧みな物語の組み立てで、映画とかドラマになってもおかしくないなーと思った。素直におもしろかった。 

ちなみに先週から息子を託児所に連れて行きはじめたので本を読む時間がなかなかとれなくて若干イライラしております。 
    このエントリーをはてなブックマークに追加 mixiチェック

10年物の20万行ほどあるWebアプリの配信部分をPSGI化したところ、先ほど無事○○Gbps単位のピークタイムをシステムの負荷をあげすぎず(アラートをあげず)に乗り切れたようです。

関係者の皆様お疲れ様でした。ご協力ありがとうございます。

最初パフォーマンスの問題があってがっかりしたけど、良いコード書けたと思うし、最終的にはちゃんと期待してたくらいのパフォーマンスが出て良かった。






ちなみにそのWebアプリっておまえの読んでるこれだよ、これ。  
    このエントリーをはてなブックマークに追加 mixiチェック

すごいヘビーな負荷を受けているPSGIアプリケーションで「なんでこれで負荷があがるの?」的な現象があったので二つほどTipを。ちなみにこれは 2013/03/06時点での話なので、もしこれをあなたが大分将来に読んでいるのなら、状況に変更がないかちゃんと確認すること!

まずこのお話の前提:mod_perlなアプリをPSGIに移行したかった。アプリはmod_perlハンドラで書かれているので、Apache::RequestをPlack::Requestに書き換えたり、ハンドラ部分をオブジェクトにしてキレイにするくらいで、基本的な構造は何も変えてない(←ここポイント)。あとはApache側とか設定をもりもりいじって、PSGIファイルを書いて、Starletでデプロイして、パフォーマンスが30%くらい悪くなった。さて、犯人は誰でしょう?

まずアプリケーションを組む側が「やっちまったなぁ?」な件:Plack::Builder::mount()を多用しすぎると大分ペナルティがある。 例えば、/foo => MyApp::Handler::Foo, /bar => MyApp::Handler::Barみたいなマッピングで処理を移譲する場合、mountでこう書けなくもないけど、

builder {
enable ...; # ミドルウェア
mount "/foo" => MyApp::Handler::Foo->new;
mount "/bar" => MyApp::Handler::Bar->new;
....
};

これはmount()することによって関数コール一個分余計に呼ぶし、それを何回も繰り返すので当然・・・遅い。今回は元々独立したハンドラが一杯あって面倒くさかったからこう書いちゃったけど、負荷が高いとよくないので、こう書いたほうがよい。

# pseudocodeだからこのまま使うなよ!
my %handlers = (
"/foo" => MyApp::Handler::Foo->new,
"/bar" => MyApp::Handler::Bar->new,
....
);
sub handle_psgi {
my $env = shift;
my $handler = $handlers{ $env->{PATH_INFO} };
if (! $handler) {
return [ 404, [], [] ];
}

$handler->handle_request($env);
}

builder {
enable ...; # ミドルウェア
enable ...;
\&handle_psgi;
}; 

ベンチはkazeburo先生のこれとかを参考に。まぁ当然の結果だけど、約2倍も処理速度がはやくなるね!

この変更をする際に、PSGIファイルから呼ばれる基本のディスパッチ関数をオブジェクトに埋め込んでいたのを一つの関数にまとめた。メソッドコールのオーバーヘッドもいらない。

次はPlack::Requestの話。今回の案件ではほぼ全てのリクエストにクエリストリングがついてきて、それをパースしないといけないんだけど、Plack::Request->query_parametersが重い。思いの外重い。

俺がランチミーティングをしてたらまたkazeburo先生が色々あさってきてくれて、query_parametersの中でuri()を2回呼んでて、なおかつこの結果はキャッシュされてない。URIオブジェクトの生成を愚直に2度行っている事と、クエリストリングをパースしたいだけなのにそもそもURIオブジェクトの生成とか必要ないだろ!ってことで以下のようなパッチを当てると5倍から10倍速くなる:

Optimize ->query_parameters
 
これは現時点で最新版のPlack(1.0016)には入ってない。

ここまで見て、Devel::NYTProfの結果にはもう最適化できそうなところが何も無かった、というところまで落とし込めた。ふー、よかったね!

・・・と思ったんだけど、よくよく考えるとこのクエリのパースってCのほうが絶対速いしCPU使わないよね・・・。ってことでCPANをQueryStringで検索したらそれらしき物がなかったのでXSで書いた:Text::QueryString

ふー、やったぜ、やれやれ。と思っていたらIRCでURL::Encode(::XS)の作者に「それ、俺のモジュールでできるし、URL::Encode::XSを使えば爆速だぜ!」って言われたのでベンチしてみたらText::QueryStringが負けたorz 多分URIデコードの部分だと思う・・・。ともあれ、すでにそういうものが存在するのであれば別にいいや、ってことでText::QueryString 0.03で別にモジュールあるよ!ってドキュメントを書いてオワコンにして、以下のようにURL::Encodeでモンキーパッチしちゃうことに:
use Plack::Request;
use URL::Encode; # URL::Encode::XSを入れておく事

{
no strict 'refs';
*Plack::Request::query_parameters = sub {
my $self = shift;
my $env = $self->env;
my $query = $env->{'plack.request.query'};
if ($query) {
return $query;
}
$env->{'plack.request.query'} =
Hash::MultiValue->new(@{URL::Encode::url_params_flat($env->{'QUERY_STRING'})});
};

これは割とマイクロな最適化だったけど、少しでもCPU使用率減らしたかったので、まぁまぁよいかな、と。

ちなみに結局アプリをホストしているサーバー単位ではApache(mod_perl 1.3)ベースの時に比べると+10%くらいの負荷ペナルティでPSGI化ができた。

というわけでまとめると、Apacheはやっぱり基本的な所では高性能。リクエスト関連のパースはやっぱりガチガチに作り込まれてるだけあってすごく低い負荷でやってのける。Perlだけでそれを代替すれば当然作り込まれたCには必ず負ける。だからPlackにちょろっと移行しただけだとやはり負荷の問題がでてくる・・・だけどそれさえもいくつかの良識的な最適化、優秀なオペレーションエンジニアとの協同作業、ある程度の試行錯誤を許してくれるデプロイ手順の確立、そして「まー、Perl遅いならCで書けばいいや」(もしくはCベースのモジュールで代替しちゃえ)という割り切りで確実・着実にApacheにもほとんどひけをとらないパフォーマンスを発揮できる、ということでした。

以上本日のPlackパフォーマンスTipsでした。 

    このエントリーをはてなブックマークに追加 mixiチェック

大変説明が難しい作品。基本設定は現実世界ではありえない設定なのでサイエンス・フィクションと言っていいのだが、起こっている事件はかなりオーソドックスなクライム・サスペンス。どこがSFかというと重なり合うように存在する二つの都市ベジェルとウル・コーマというものが存在する。二つの年は物理的に非常に近い場所にあるのだが、お互いの市民は相手方の人や建物の存在を「見て」はいけないし、存在を認識してもいけない。ベルリンの壁のような物があるわけでもないのに、この都市の住民達はそれを教育によって「見て」も「見ていない」ようにする。もし正規の手続きを経ずに都市間を越境しようとしたり相手の都市に関わったりするとそれは「ブリーチ行為(breach)」と見なされ、全ての権力を超越したブリーチという集団によって片付けられてしまう。そんな中で起こる殺人事件・・・という長い説明を必要とする設定。

最初は設定を飲み込むのに若干時間がかかるけど話の運びはうまいし、描写も巧み。ラストはちょっと駆け足感があったけど、納得できるものだった。結構おすすめ!
    このエントリーをはてなブックマークに追加 mixiチェック
カテゴリー
記事検索
メッセージ

名前
メール
本文
アーカイブ

このページのトップヘ