Preforkした上でAnyEventのloopを動かすPlack::Server::AnyEvent::Preforkを、先週のPlack Hackathonの時間で形にしてgithubにpushしました。
はなぼくろ師との共作です。
目的は、AnyEventでもマルチコアを使いたいよねという理由ですが、それほど一般的な利用はないと思います。plackupの方でprefork処理を行うとかいう話もあったりなかったりなので、しばらくCPANにはアップロード予定ありません。不足している部分もありますので、fork & patchウェルカムです
Hello Worldだけのテストで生AnyEventとの比較 ベンチマークをしたサーバはVMware ESXi上の仮想マシン。一応CPU 2つ割当てある
起動はこんな感じ
plackup -a hello.psgi --server AnyEvent::Prefork --max_workers 2 --max_reqs_per_child 10000 --port 8080 --env production
AnyEvent
Concurrency Level: 100
Time taken for tests: 3.941 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 680000 bytes
HTML transferred: 40000 bytes
Requests per second: 2537.41 [#/sec] (mean)
Time per request: 39.410 [ms] (mean)
Time per request: 0.394 [ms] (mean, across all concurrent requests)
Transfer rate: 168.50 [Kbytes/sec] received
AnyEvent::Prefork
Concurrency Level: 100
Time taken for tests: 2.673 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 680000 bytes
HTML transferred: 40000 bytes
Requests per second: 3740.71 [#/sec] (mean)
Time per request: 26.733 [ms] (mean)
Time per request: 0.267 [ms] (mean, across all concurrent requests)
Transfer rate: 248.41 [Kbytes/sec] received
preforkにするだけで、req/secが50%アップしてます。 これで多少CPUを使ったり、block処理が入ってもAnyEventで動かすことができるんじゃないかなと思います。
現在残っている課題としては、子プロセスがmax request per childに達した際にまず、新規のacceptを行わないようにしていますが、その際に既存のコネクションをいつまで保持するかの処理が入っていない点です。streamingをやっていた場合は新規のacceptを受けない状態でいつになってもプロセスが死なない→新規のプロセスが立ち上がらない→リクエストを全く受けれない。なんていうことが起こることです。 現状としては、アプリケーションに応じてそのあたりの処理を入れていくしかないと思われます。
会社の最新サーバでも試してみたいな。