uzullaがブログ

uzullaがブログです。

ReactPHP+HHVMは使い物になるのか?

先日いれた謎のHHVM状態ではありますが、メゲないでReactPHPの話し。

発端

ちょっと前に、reactPHP+HHVM+nginxでSymfonyを動かそうぜ!という非常にワクテカ感あふれるイケてる記事があった、こちらです。
http://marcjschmidt.de/blog/2014/02/08/php-high-performance.html

これがそのProcess Managerである。内部的にphpをフォークして、マルチプロセスな感じにしている。
https://github.com/marcj/php-pm


まあ、nginxとHHVMはもう普通に使われているようなものなので、コメントは特に無い。
残るReactPHPだが、まあPHPerなら知ってるだろうけどいわゆるノンブロッキング、イベント駆動型のサーバーを作成することができる。PHP自体がサーバとして動くというあたり実に夢あふれるシロモノになっております。

http://reactphp.org/
公式サイト上ではv0.3.0でとまっているが、実際にはv0.4.0がリリースされている。結構前に色々ためしてみたけど、まだこれはつかえんな…という印象で諦めた経緯があります。


ただ、今回Symfonyを上で動かすような人がでたということは、前ちょっと調査した限りでは「Just sample snippet」っぽかったhttp server実装がまともになったのかな…、と調査してみたので、その感想文です。

オチとして、つらい。

前提として、ReactPHPを普通のアプリケーションサーバーとしてつかうのは、まだかなりつらい。簡単にいって相変わらずReact\HTTP\Serverの実装はまだまだ感ある。
(0.4.0の話なので、別ブランチでは実装されている…とかあるかもしれないが)

・POSTがうごかない(単にPostのクエリパースが未実装)
・勿論Multipartもうごかない(クエリが4kByte以上は現状殺している)

はい、普通の人解散です、お疲れ様でした。


まあ、逆にいえば

・GETは使える(ヘッダーが4K限界というハードコードがあるが)
・まあ、実際速いっちゃ速い

感じであり、(PHPerの妄想的には)やっぱイケてる感じになりそうだな…うまくハマればな!!

ところで、じゃあ発端のブログはなんだったのか

まあ…あんまり実用性はなかったw!夢有る煽り記事だった!

ただ、コード自体はおもしろいし学びある感じはありました。ワーカーを沢山うごかすというのは良い、こんど実際試そうと思う。
(アプリコードとの接点はブリッジインターフェースにきりだされていて、まあReactのRequest/Responseオブジェクトを使うので済む限りは比較的簡単につかえそうだった)

まあーなんていうかー、POSTできないのつらすぎるよね。GETだけとかヤバイでしょ。

まあ、さらっと全部あきらめて、「php://input」相当のIFを提供してしまい、アプリサーバーでどうにかしろや!」という方向でもいいんだけど今のreactはそうもなってないからつらいな。

POST使えないのどうするの

まあ、\React\Http\ServerとRequestHeaderParserを自分で書けばいいんですよ!(オッ単なるマジレスだ)

実際の所、POSTのapplication/x-www-form-urlencodedは別にパースむずかしくないのでどうということはない。
(メモリのことをヨソにすれば)あとはバッファの最大サイズをふやせばよい。


問題は、ちゃんとやるならmultipart/form-dataサポートも必要になる事であり、ファイルアップロードするにはこいつが必須だが、非常に面倒なことだ。
Boundaryの分割処理を実装しないといけないし、メモリ効率的にいえば、base64エンコードされておくられてくるデータをストリーム的に処理してテンポラリファイルなどに書き出す必要がある。勿論元のファイル名をひろって配列にいれて…云々。
…つまり$_FILES相当の実装をするのはけっこうダルい。(まあ、こだわらず「オンメモリにいれてもいいんだ、メモリ大富豪!」ということならわりとどうとでもなるとは思っているが)

とまあグダグダ言ってもしかたないので

https://github.com/uzulla/ReactPHP_PostSupportSample

ためしに実装してみました。multipartは実装してないけど、とりあずPostのパラメータがとれる。

POSTボディの終端をどうやって知るのか、Content-Lengthを見る以外にあったような気もするんだけど、ヌルバイトでもなかった気がするし、まあ…。
KeepAlive?Chunked?知らない子ですね!(まあ、やれば実装出来るけど、検証たいへんそう)

(ちなみに上のrepoはReactPHPでつくるウェブアプリのサンプルとしても見れます)


はー、本家もTODOってかいてあるし、早くここらへん実装されてほしい*1

で、だ。

話はかわって、HHVMとPHP5.5.7をReactPHPで書いたしょっぱいコードをまわしてみた(上のコードと同一ではないが、ログ書き出しをオフったようなもの)
意味があるのかないかわからんが、HHVMはウォームアップ的に-c 1 -n 5000を事前に回しています。

ab -c 10 -n 5000 'http://localhost:8080/'

で雑に回した結果が以下となります。

Requests per second: 4737.02 [#/sec] (mean) by HHVM 2.4.1
Requests per second: 2277.15 [#/sec] (mean) by PHP 5.5.9
Requests per second: 1947.89 [#/sec] (mean) by PHP 5.4.19

*2

手元のMacでうごかしてますのでばらつきは盛大におこりますし、平均とかいわず高めの数字をチョイスしました。
結果倍以上はHHVMのほうが回りますね。*3さすがHHVMだぜ!

ただ、\React\EventLoop\StreamSelectLoopにちょっと手を入れる必要があった(NULLをforeachしようとする箇所があり、T_FOREACHに大量のエラーログがでた)

まとめ

まあ、機能が無い分?それなりに速度はでている。ただイベント駆動なのでそのままではマルチコア生きないし、なぜか一瞬固まる現象が散見されるのでnginxでバランスさせたほうがよさそう(それには冒頭のPMみたいなのをつかうとよいとは思う)。
安定性はよくわからない。そもそもReactPHPはFATAL系のエラーが発生するとおちるので(まあ、他の言語ではあたり前だが、PHPerにはなじみがない概念だ)コードがひどいと勿論安定しない。


兎に角数字を稼ぐような狭い用途にはよいかもしれないが*4、まだつかうにはローレベルを理解してちゃんと書かないといけない感じであり「それPHPでやるべきことなの?」ってまた言われる感じがすごいぜ*5


そしてReactPHPとかZephirとかを話せる知り合いがいなくて大変きびしい、知り合いをふやさなければならない。

どうしてもしなければいけない宣伝

もうすぐ私が一部担当した書籍が出ます!!!
ReactPHPとかHHVMとかそういうのは攻めてなく、わりとゆるふわな感じです。

Webアプリエンジニア養成読本
和田 裕介, 石田 絢一 (uzulla), すがわら まさのり, 斎藤 祐一郎

良い本になったと思います!詳しくは先日のエントリをご覧ください。
http://uzulla.hateblo.jp/entry/2014/02/23/221757


また、発売を記念して、池袋のジュンク堂書店にてイベントを行います。
予約にはまだ結構空きがあるらしく、「電話予約というハードルがたかすぎるのでは?」という話もありますが、こちらも是非宜しくお願い致します。

http://www.junkudo.co.jp/mj/store/event_detail.php?fair_id=4314

「『Webアプリエンジニア養成読本』(技術評論社)刊行記念
Webアプリエンジニアが出来るまで」
ジュンク堂書店 池袋本店
開催日時:2014年03月20日(木)19:30 ~


こちらからは以上です。

*1:こういうのはプルリク案件だといわれれば、まあそうなのかもしれないが

*2:上のがそもそもそんなに速くない、というのは手元のMacが悪いという話だとおもいます…

*3:同時接続をへらすと、もうちょっと差が出るかんじ

*4:コネクションプールをつくったり、ルーターやテンプレートエンジンのシングルトンができる!!!PHPなのに!!!

*5:ちなみに、書いてる最中ずっと「これはPerlのAnyEventだな…」と思っていた