Home > Uncategorized > PHP 5.5 vs HHVM vs Node.js Benchmark

PHP 5.5 vs HHVM vs Node.js Benchmark

I wanted to run a benchmark of HHVM against php 5.5. I also threw in Node.js since it is pretty fast. I was really surprised by the results.

Check out part 2 and part 3 of the benchmark:

PHP 5.5 vs HHVM vs Node.js Benchmark part 2

PHP 5.5 vs HHVM vs Node.js Benchmark part 3

Since the HHVM team used the Fibonacci benchmark (http://www.hhvm.com/blog/1817/fastercgi-with-hhvm) I tried the same. What I did was vary the number of fibonacci numbers computed and measured the time taken. Obviously this is a lot more computationally intensive than what most web apps do. This test has a O(2^n) time complexity and as we hit q=30 we are making a billion+ recursive calls. The tests were run on a ubuntu 12.04 machine with about 2gb of ram.

I used the following ab command:
ab -n 100 -c 10 http://gimagesearch.com/?q=30

I used the average time taken across all connections.

Version of php:
PHP 5.5.7-1+sury.org~precise+1 (cli) (built: Dec 12 2013 21:37:40)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
with Zend OPcache v7.0.3-dev, Copyright (c) 1999-2013, by Zend Technologies

version of hhvm:
HipHop VM v2.3.2 (rel)

version of node:
v0.10.24

I tried using node as a server and tried using nginx as a frontend that proxied the connection to the node server, but they both had pretty similar results. So I decided to use the case where node was run as the main server.

here is the code for the php:

$input = $_GET['q']; 
function fibonacci ($n) {   
  if ($n == 1 || $n == 2) {     
    return 1;   
  } else {     
    return fibonacci( $n - 1)+fibonacci( $n - 2 );   
  } 
} 
 
echo(fibonacci($input));

Here is the code for node:

var http = require('http');
 
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
var url = request.url.split("/");
var num = parseInt(url[url.length-1]);
var out = fibonacci(url[url.length-1]);
 
response.end(out.toString());
});
 
function fibonacci (n)
{
  if (n == 1 || n == 2)
  {
    return 1;
  }
  else
  {
    return fibonacci( n - 1)+fibonacci( n - 2 );
  }
}
 
server.listen(80);

Finally the results:

q php5.5 hhvm node
1 25.361 24.951 24.941
2 25.081 25.081 25.571
3 26.422 25.071 27.372
4 25.281 25.391 25.661
5 26.462 25.471 27.112
6 25.021 28.252 44.713
7 25.721 28.432 28.972
8 28.592 25.681 26.562
9 25.261 25.291 25.601
10 25.591 25.571 25.731
11 24.941 34.152 24.901
12 27.322 41.072 26.472
13 25.011 25.491 26.512
14 25.231 25.681 27.322
15 24.511 26.142 26.722
16 28.122 25.021 25.091
17 43.582 25.121 25.301
18 27.232 27.942 26.572
19 25.431 25.081 26.232
20 37.212 26.642 25.251
21 24.211 25.641 28.532
22 24.771 56.913 25.671
23 24.991 24.891 24.941
24 24.881 28.222 26.222
25 24.761 26.902 29.972
26 24.561 25.501 24.991
27 24.811 26.222 24.541
28 26.672 24.501 25.361
29 48.973 24.521 24.331
30 88.515 27.032 36.782
31 142.34 24.921 28.172
32 242.48 24.921 46.683
33 368.87 26.001 73.464
34 582.34 35.892 116.76
35 893.97 55.973 191.97

graph

As you can see normal php starts to blow up at q=29. hhvm hangs with node and over takes it when q>31. When q=35, the time taken by hhvm is almost 16x better than php5.5 and almost 4x better than node. Obviously this use case might not be representative of many web apps, but the HHVM team deserves a lot of kudos. The fact that node is single threaded and hhvm is multithreaded is probably why hhvm can beat node. In a future benchmark I might setup multiple node servers behind nginx. However HHVM is a beast when compared to php 5.5.

Update:

I wrote a multithreaded version of the Fibonacci code, but it crashes when q=31

  var http = require('http');
  var Worker = require('webworker-threads').Worker;
  var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  var url = request.url.split("/");
  var num = parseInt(url[url.length-1]);
 
  var worker = new Worker(function(){
   function fibonacci (n)
   {
    if (n == 1 || n == 2)
    {
     return 1;
    }
    else
    {
     return fibonacci( n - 1)+fibonacci( n - 2 );
    }
   }
 
   onmessage = function (oEvent) {
    postMessage(fibonacci (oEvent.data));
   };
  });
 
  worker.onmessage = function(e){
   response.end(e.data.toString());
  };
 
  worker.postMessage(num);
 
});
 
server.listen(80);

The results:

q Php 5.5 Node
1 12.741 13.441
2 12.581 13.721
3 12.471 13.571
4 12.531 13.301
5 12.581 13.111
6 12.901 13.341
7 13.591 14.671
8 12.731 13.521
9 12.691 12.721
10 13.071 13.221
11 14.951 14.471
12 13.511 13.051
13 14.101 12.801
14 12.881 13.061
15 13.661 13.121
16 13.271 13.331
17 15.292 15.092
18 12.361 18.582
19 14.381 19.622
20 12.311 19.532
21 43.654 27.473
22 12.791 21.232
23 12.841 24.792
24 12.661 18.252
25 12.731 20.922
26 12.821 23.142
27 12.701 22.322
28 14.121 21.162
29 13.311 22.402
30 13.401 26.953
31 13.851
32 22.232
33 36.504
34 52.615

As you can see even with a multithreaded version of node hhvm has some impressive performance.

Categories: Uncategorized Tags:
  1. Stan
    December 27th, 2013 at 14:46 | #1

    Hello, thanks for posting these tests. What web server was php run with? Was it run with nginx? I’m also curious if you ran hhvm in server mode or if you used the new fcgi implementation. Thanks!

    • samFisher
      December 27th, 2013 at 15:34 | #2

      It was run with: nginx version: nginx/1.1.19

      hhvm was run in fastcgi mode daemon mode.

  2. Adri
    January 12th, 2015 at 01:53 | #3

    Did you run node in cluster mode, so that it can use all cores (if available)?

  3. test
    January 16th, 2016 at 13:09 | #4

    Hmm, don’t take it a wrong way. I think this test wan’t really showing the power of Nodejs, as we know NodeJS is pure NIO based on Event loop, that means, the request will not block even when the IO still running at background. For example, if we run NodeJS mysql and PHP mysql to fetch data in 1000 loops, probably PHP will win, but that doesn’t mean PHP is better, in a real circumstance, when we try -c 500 -n 500 to a PHP app and a NodeJS app, the PHP app will dramatically slow because Apache running out of thread with PHP, but NodeJS app still handle well, as it don’t really consume that number of thread at all.

  1. April 16th, 2015 at 01:22 | #1


− one = 8