読者です 読者をやめる 読者になる 読者になる

八発白中

はてなブログに引越しました。

Day 14: fast-http

advent-calendar/2016

これは fukamachi products advent calendar 2016 の14日目の記事です。

今日はfast-httpについて話します。埋め込みツイートが多いですが手抜きではありません。

Common Lispは高速か

Common Lispは高速だという話を界隈ではよく聞きます。噂によればC++やCよりも高速なプログラムを書くことができるとさえ言われています。

Cで書くコードの方がCommon Lispで書くより速いって人がいたら、それは彼のCの技量が高すぎるってことだね。

“If you can't outperform C in CL, you're too good at C.”Eric Naggum

昨日紹介したwebsocket-driverを書いたとき、好奇心からCommon Lispの実行速度というのはどれほどのものだろうと計測してみました。比較対象はNode.jsのwebsocketモジュールです。

勝負はあっけなく終わりました。書き上げてとりあえずベンチマークを取ってみようという段階で、僕が書いたCommon Lispの実装のほうが圧倒的に速かったのです。しかも、型宣言やoptimize宣言や関数のインライン化などもすればもっと速くなる余地がある状態でです。

これは当時の意気揚々としたツイートです。

高速に動くということの優位性

Common LispでWebアプリケーションが書けると言っても、じゃあ他と比べたときの優位性とはなんだろうという答えの一つがこれでした――Common Lispは速い。

これだけ抽象度の高い言語でありながらGoやC++と比べられるほどのパフォーマンスが出るのだから、これは強みになります。起業を考えていた自分はこの強みを活かして技術優位性としようと考えていました。

けれど、まだ道のりは始まったばかりです。

やっぱりCommon Lispは遅い?

河西くんTwitterで会話するようになったのはこの頃でした。先程のツイートを見てリプライをくれています。

twitter.com

Wookie *1がNode.jsのhttpモジュールよりも遅い、というのです。まじかよ、と思って実際に計測してみると、Node.jsはWookieよりも2倍も高速でした。

twitter.com

Wookieを高速化する

Common Lisp自体はNode.jsより遅い言語ではないというのはwebsocket-driverで知れたことです。ということは、何か遅い原因があるはずです。僕はWookieのソースコードを見てどうにかNode.jsより高速にしてやろうと決めました。

Wookieをプロファイリングすると内部で使っているHTTPパーサーのhttp-parseボトルネックとなっていることがわかりました。

twitter.com

中身を見てみると納得です。パーサー部分はナイーブに正規表現で行っていました。subseqなどの呼び出しも見られ、何度もメモリアロケーションがされているのがわかります。

このときの開発の状況はツイートによく残っています。http-parseのベンチマークを取って高速化してPull Requestを投げることを繰り返していると、じきにκeenも参加し始めました。

そして最終的にhttp-parseはWookieの最大のボトルネックではなくなりました。

でもまだ遅い

それでもWookieはまだNode.jsより少し遅い。そこで抜本的に改善するために一からHTTPパーサーを書きました。それが「fast-http」です。

twitter.com

リリース当時はhttp-parseの10倍高速でしたが、現在はさらに高速化されて120倍以上高速になっています。最終的にCで書かれたhttp-parser (Node.jsで使われているもの) よりも高速になったため、それをブログとしてまとめ、それなりの反響を得ました。

blog.8arrow.org

高速かつ抽象度の高いプログラム言語としてCommon Lispは十分に戦えそうだ、という実感を持った瞬間です。

上のエントリーからCommon Lisp界隈で「高速なプログラムを書こう」というムーブメントが起きたように思います。実際にCよりも速いコードが書けたぜ、っていうのはインパクトがあるのでしょうね。

でもまだまだまだまだ遅い

けれど、ここまでやってもWookieはNode.jsに勝てませんでした。

twitter.com

使っているイベントライブラリがlibevent2であることが問題なのだろうか?というツイートを残しており、Wookieの作者から「libuvバックエンド (Node.jsと同じもの) にするつもりだよ」とリプライがきています。

ここからまた面白くなるのですが、詳しくは明日のWooの回に取っておくとします。

おわりに

fast-httpはGitHubで公開されており、Starは252です。

明日のアドベントカレンダーは15日目のWooについてです。お楽しみに。

*1:Common Lispの非同期Webサーバー。当時はlibeventベース、現在はlibuvベース。