FasterCGI with HHVM
hhvm.com
hhvm.com
This note hints at a missed opportunity to employ what some like to call "unix factoring": the listen(2) call can occur outside of your FastCGI worker program, which then only has to call accept(2) on the inherited descriptor, and implement the FastCGI protocol.
Why do it this way?
1. Beyond the accept(2) call, your worker program is now network agnostic.
2. Guess what, you can now test your worker program by feeding it FastCGI protocol data directly on stdin. Just add a mode that uses stdin instead of the fd returned by accept(2).
3. For easy TCP socket support, run your worker under something like this tiny program [1]. For easy Unix Domain socket support, run your worker under something like this tiny program [2]. Your worker program doesn't change because the networking concern has been separated out.
4. If you want, you can put a program which keeps a preforked worker pool between the the listener program and the worker program. This separates out the concurrency concern.
5. No real performance downside; listen(2) is called once for a long-running server process.
[1] tcplisten : https://gist.github.com/acg/4211098
[2] unixlisten : https://gist.github.com/acg/8016689
Yes, we used opcode cache in PHP. I definitely don't consider myself to be an expert on PHP configuration. I used the default settings. I was obviously also very suspicious of the results that we got. To the extent, that I consulted a few people about what could be improved about the PHP setup. I remember opcode cache was the first thing I checked, since it's something everyone knows and talks about. It was turned on.
I will update the blog post first thing tomorrow (sorry guys, it's the middle of a night here in Poland, so don't feel like doing it right now).
Cheers.
If you would like to have the test re-run, you'll have to harass some real FB engineers, since the test was performed on a devbox that I don't have access too anymore. You're also more then welcome to try it yourself and post some alternate benchmarks.
I think I can promise to link to your results from the blog post.
I'll re-run anything that you need to re-run if you tell me what to do.
I tried tweaking the nginx setup, especially the tcp_nodelay & keepalive_timeout settings. It provided maybe 15% speed up, nothing dramatic. I probably didn't collect enough datapoints to be able to reliably tell. In the end, I sticked to the nginx defaults.
function fib($n) { if ($n <= 1) { return $n; } else { return fib($n - 1) + fib($n - 2); } }
$n = 30; $r = fib($n); echo "Fibonacci number $n is $r\n";
As indicated in the benchmark, it's a dumb exponential implementation.
Apart from that, having FastCGI support is of course nice.
Really I think this sort of thing should be encouragement to make the opcode cache no longer a default-off additional thing. There's no good reason to have a php deployment -- even one that's just for dev purposes -- that doesn't use an opcode cache.
And we can agree FastCGI support is nice indeed.
1 - https://github.com/facebook/hhvm/tree/master/hphp/runtime/se... 2 - https://github.com/kakserpom/phpdaemon/tree/master/PHPDaemon...
Many of the older extensions that were imported back in the HPHPc days are in C since they were much easier to port from php-src if we didn't have to translate the language.
As for why this was't in PHP, two reasons. It was easier to stay in the language since our event loop code was already in C++, and most of the gains we get from writing library code in PHP comes from not having to cross a language barrier from userland code. The event loop is not the best place for that.
99% of projects out there, from Symphony to Wordpress, are still PHP 5.3 compatible. I don't know any major project requiring traits for example.
http://www.hhvm.com/blog/875/wow-hhvm-is-fast-too-bad-it-doe...
http://www.hhvm.com/blog/1499/locking-down-for-performance-a...