tokuhirom's Blog

Perl5 での Plack に当たる Crust をみんなで作った話

この記事は Perl 6 Advent Calendar 2015 の1日目です。

Perl 6 は、2015年のクリスマスにリリースされることになっており、我々としてはそれを待ち受ける必要があると考えました。

Perl6 がリリースされた暁には、いろいろ遊ぼうかなという気持ちをみなさんお持ちだと思います。 Perl6 には夢が詰まっており、様々な機能が含まれている夢の言語です。

そういった、夢の機能については今後、クリスマスまでの間に、語られていきますが、本稿では、現実的な話をします。


今年のクリスマスに Perl6 がリリースされるぞ、という宣言がでたわけですが、そうなってくると、Perl6 をクリスマスから早速遊びたいなと思うわけですよね。

そして、私は web engineer なので、 Perl6 が出たら早速 web application を書きたいと思うわけです。

しかし、そこで気づいてしまう。Perl6 には Plack のようなものが無いと!

Perl6 に Plack のようなものがないし、当時まともな httpd の実装が存在していなかったのです! (実際には存在はしていたのですが、multi thread 対応していないし、なぜか当時の MoarVM は listen の backlog が 1 にハードコードされているためにまったく実用的ではなかったのです。この listen のバックログがハードコードされている問題は現在では修正されています)

これではいけない。と気づくわけです。まともな httpd が必要だ。 とりあえず fork(2) があれば、listen backlog が 1 にハードコードされているというハードな環境下でもなんとかなるだろうと思って、まず NativeCall ( Perl6 から FFI で C 関数をコールする機能) を使って fork を呼ぶようにしてみました。これはなかなかうまく動作したのですが、Mac で動作しないという問題が発見されました。

なぜか。

MoarVM は内部で libuv を利用しており、あらゆるソケット処理に libuv を利用しています。 libuv は fork をサポートしていません。より具体的に言うと mac の kqueue は fork をサポートしてないので、完全に詰みました。

対策として、ソケットライブラリを全部 NativeCall で実装することも考えたのですが(実装もしたのですが)、完全に本質を見失っている感じがしてきたので、この方針は諦めることにしました。


そうこうしているうちに、IO::Socket::Async ベースならわりと動くっぽいのではないかという話になり、IO::Socket::Async ベースで実装する方針に転換しました。

何度か書き直したのですが、まあそこそこ動くようになりました。

そのそこそこ動く実装が HTTP::Server::Tiny です。これは Perl5 の有名な httpd 実装である kazuhooku 氏による Starlet を参考に実装されており、HTTP/1.1 に対応した高速なサーバーです。 (Perl6 でできる範囲としてはかなり高速になるように実装しています。期待したパフォーマンスが出ていなければ、それは、、)

https://github.com/tokuhirom/p6-HTTP-Server-Tiny/


そういうわけで、HTTP::Server::Tiny ができたので、あとは Plack 相当のレイヤーを実装しようということになりました。

そこで、下記12名の Perl Monger が集まり、Plack を Perl6 に移植するプロジェクトに乗り出しました。

https://github.com/tokuhirom/p6-Crust

結果として、2015年12月1日時点でほぼ Plack の機能を実装しております。 例えばイカのように実行すれば、さくっと httpd が立ち上がります。めっちゃ便利。

crustup -e 'sub { 200, [], ["OK"] }'

具体的にはイカのものが完備されています。


そんなわけで、ウェブアプリケーションをかく準備は整っています。

あとは Perl6 のリリースを待つだけや!!!!

明日は karupanerura さんの 無限リストであそぶ です。

http://qiita.com/advent-calendar/2015/perl6