Skip to content

Instantly share code, notes, and snippets.

@nkt
Last active September 27, 2023 08:24
Show Gist options
  • Star 92 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save nkt/e49289321c744155484c to your computer and use it in GitHub Desktop.
Save nkt/e49289321c744155484c to your computer and use it in GitHub Desktop.
ReactPHP vs Node.js
var http = require('http');
var data = {
'code': 'ok',
'error': false,
'payload': 'Hello World'
};
var app = function (req, res) {
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(data));
};
var server = http.createServer(app);
server.listen(1337, function() {
console.log("Server running at http://127.0.0.1:1337");
});
<?php
require 'vendor/autoload.php';
$data = [
'code' => 'ok',
'error' => false,
'payload' => 'Hello World'
];
$app = function ($request, $response) use($data) {
$response->writeHead(200, array('Content-Type' => 'application/json'));
$response->end(json_encode($data));
};
$loop = new React\EventLoop\LibEventLoop();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);
$http->on('request', $app);
echo "Server running at http://127.0.0.1:1337\n";
$socket->listen(1337);
$loop->run();

wrk -t4 -c400 -d10s http://127.0.0.1:1337/

PHP

Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     7.02ms    6.94ms  82.86ms   85.27%
    Req/Sec   827.17    552.85     2.38k    66.54%
  22543 requests in 10.07s, 3.61MB read
  Socket errors: connect 151, read 22680, write 86, timeout 0
Requests/sec:   2238.19
Transfer/sec:    367.20KB

Node

Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    20.34ms    4.50ms 125.04ms   97.89%
    Req/Sec     3.09k     1.93k    6.06k    55.00%
  122838 requests in 10.02s, 23.66MB read
  Socket errors: connect 151, read 69, write 73, timeout 0
Requests/sec:  12263.37
Transfer/sec:      2.36MB
@devsdmf
Copy link

devsdmf commented Oct 31, 2015

Hello Nikita, I loved this benchmark comparing theses two powerful technologies, could you do a new benchmark using the PHP 7 beta and the new Node 4.1.1 ?

@ssjssh
Copy link

ssjssh commented Nov 27, 2015

👍

@Zizaco
Copy link

Zizaco commented Feb 10, 2016

@nkt Try with PHP7 😉

@appkr
Copy link

appkr commented Feb 27, 2016

I've tested this in Ubuntu 14.04 VM.

Interpreter Version

vagrant@homestead:~/benchmark$ php --version
PHP 7.0.3-10+deb.sury.org~trusty+1 (cli) ( NTS )

vagrant@homestead:~/benchmark$ node --version
v5.7.0

PHP Test

vagrant@homestead:~$ php index.php

# at new window
vagrant@homestead:~/benchmark$ wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     8.10ms   59.71ms   1.61s    99.30%
    Req/Sec     2.64k     2.41k    8.10k    72.90%
  84281 requests in 10.10s, 13.50MB read
  Socket errors: connect 0, read 84570, write 0, timeout 3
Requests/sec:   8344.60
Transfer/sec:      1.34MB

Node Test

vagrant@homestead:~$ node index.js

# at new window
vagrant@homestead:~/benchmark$ wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    24.38ms   12.77ms 256.05ms   91.53%
    Req/Sec     4.19k     1.07k   10.92k    94.40%
  158772 requests in 10.09s, 30.59MB read
Requests/sec:  15727.79
Transfer/sec:      3.03MB

reactphp_vs_node

Is there anyone who can try HHVM?

@suside
Copy link

suside commented May 3, 2016

For HHVM I had to use StreamSelectLoop:

$ php -v
HipHop VM 3.13.1 (rel)
Compiler: tags/HHVM-3.13.1-0-g4f382ad928a6e2a0607a8dcb251002aca77f11f6
Repo schema: 655b5912cb8136e9df6f9be972153e38ac446e0f

$ wrk -t4 -c400 -d10s http://172.17.0.2:1337/ 
Running 10s test @ http://172.17.0.2:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   123.94ms  145.14ms 350.89ms   67.00%
    Req/Sec   187.64    255.19   717.00     81.82%
  400 requests in 10.09s, 65.62KB read
Requests/sec:     39.63
Transfer/sec:      6.50KB

PHP with ExtEventLoop:

$ php -v
PHP 7.0.4-7ubuntu2 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

$ wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    41.30ms   40.14ms 216.68ms   91.91%
    Req/Sec   129.25    293.47     0.90k    87.50%
  346 requests in 10.07s, 56.77KB read
Requests/sec:     34.35
Transfer/sec:      5.64KB

Composer versions:

$ composer info     
evenement/evenement v2.0.0  Événement is a very simple event dispatching library for PHP
guzzlehttp/psr7     1.3.0   PSR-7 message implementation
psr/http-message    1.0     Common interface for HTTP messages
react/cache         v0.4.1  Async caching.
react/child-process v0.4.0  Library for executing child processes.
react/dns           v0.4.2  Async DNS resolver.
react/event-loop    v0.4.2  Event loop abstraction layer that libraries can use for evented I/O.
react/http          v0.4.1  Library for building an evented http server.
react/http-client   v0.4.10 Asynchronous HTTP client library.
react/promise       v2.4.0  A lightweight implementation of CommonJS Promises/A for PHP
react/react         v0.4.2  Nuclear Reactor written in PHP.
react/socket        v0.4.3  Library for building an evented socket server.
react/socket-client v0.4.5  Async connector to open TCP/IP and SSL/TLS based connections.
react/stream        v0.4.3  Basic readable and writable stream interfaces that support piping.

And node:

$ node -v
v5.5.0
$ wrk -t4 -c400 -d10s http://127.0.0.1:1337/ 
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    32.25ms    6.55ms 283.20ms   91.87%
    Req/Sec     3.02k   456.55     4.99k    86.25%
  120144 requests in 10.06s, 23.14MB read
Requests/sec:  11939.26
Transfer/sec:      2.30MB

All tests on one machine, any ideas why php/hhvm is performing so poor?

@tdatu
Copy link

tdatu commented Aug 7, 2016

hello all, thanks for sharing the result. I myself is considering this test as I'm interested in investing time on reactPHP, however from the result above even with php 7, it seems like node delivered more in terms of request / sec basing on appkr's test. but I can also see that node's latency is significantly higher. Question here, which would you prefer? lower latency or higher request/sec?
Thanks in advance! Please pardon me if I misunderstood / or made wrong assessment on the numbers.

@sinasalek
Copy link

@suside StreamSelectLoop you used is not suitable for event driven application, it's just a fallback in case Event extension wasn't available

@sinasalek
Copy link

Node.js v6

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 33.73ms 11.66ms 276.14ms 89.75%
Req/Sec 2.78k 246.07 3.09k 92.50%
110714 requests in 10.01s, 21.33MB read
Requests/sec: 11061.55
Transfer/sec: 2.13MB

PHP 5.6 + StreamSelectLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 21.47ms 100.17ms 1.75s 98.43%
Req/Sec 797.22 161.79 1.25k 63.00%
31743 requests in 10.01s, 5.09MB read
Socket errors: connect 0, read 31743, write 0, timeout 29
Requests/sec: 3169.99
Transfer/sec: 520.08KB

PHP 5.6 + LibEventLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 22.29ms 99.64ms 1.77s 98.33%
Req/Sec 759.40 211.63 1.30k 69.00%
30235 requests in 10.01s, 4.84MB read
Socket errors: connect 0, read 30250, write 0, timeout 22
Requests/sec: 3020.05
Transfer/sec: 495.48KB

PHP 5.6 + ExtEventLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 21.13ms 92.95ms 1.89s 98.73%
Req/Sec 721.25 192.93 1.16k 62.75%
28728 requests in 10.01s, 4.60MB read
Socket errors: connect 0, read 28725, write 0, timeout 26
Requests/sec: 2869.25
Transfer/sec: 470.74KB

PHP 5.6 + LibEvLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 27.46ms 121.37ms 1.62s 97.54%
Req/Sec 766.31 243.96 1.25k 67.50%
30526 requests in 10.01s, 4.89MB read
Socket errors: connect 0, read 30525, write 0, timeout 23
Requests/sec: 3048.09
Transfer/sec: 500.08KB

PHP 7.0 + StreamSelectLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 33.61ms 152.67ms 1.93s 96.21%
Req/Sec 1.18k 342.69 2.07k 65.25%
46961 requests in 10.01s, 7.52MB read
Socket errors: connect 0, read 46960, write 0, timeout 37
Requests/sec: 4691.54
Transfer/sec: 769.71KB

PHP 7.0 + ExtEventLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 30.01ms 132.79ms 1.92s 96.86%
Req/Sec 1.04k 411.40 2.26k 65.99%
41411 requests in 10.01s, 6.63MB read
Socket errors: connect 0, read 41409, write 0, timeout 48
Requests/sec: 4135.73
Transfer/sec: 678.52KB

ReactPHP 0.4.1 + PHP 7.1 + StreamSelectLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 24.44ms 121.70ms 1.88s 97.26%
Req/Sec 1.18k 316.86 1.96k 68.00%
47053 requests in 10.01s, 7.54MB read
Socket errors: connect 0, read 47053, write 0, timeout 36
Requests/sec: 4698.87
Transfer/sec: 770.91KB

ReactPHP Dev + PHP 7.1 + StreamSelectLoop

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 33.93ms 149.99ms 1.88s 95.62%
Req/Sec 1.39k 406.67 2.76k 68.25%
55544 requests in 10.06s, 8.90MB read
Socket errors: connect 0, read 55543, write 0, timeout 46
Requests/sec: 5520.35
Transfer/sec: 0.88MB

Notes:

  • PHP 7 is considerably faster
  • There is not much difference between PHP 7 and PHP 7.1 in this case
  • The result on different platforms is not consistent and highly dependent, for example on a virtual machine using ubuntu i couldn't get pass 70 req/sec!! comparing to two nodejs 12,000 req/sec
  • In some cases StreamSelectLoop is actually quite sufficient and no extension is really needed. but i'm also suspicous because, because extensions should be much faster, so they might be some sort of a limit on Linux.
  • Note that it seems nodejs uses libuv which is a crossplatform asynchronous I/O library, good news is that PHP 7 also supports it, reactphp does not yet support it but hopefully in near future it becomes PHP standard library and included by default in core
  • If there is a PHP project that requires socket server and an even loop in general, there result is satisfiing enough that eliminate the need to port the whole thing to nodejs

Note that we are using ratchet-php as light WAMP socket server for two years now, it used to be buggy and resource hug but since the last year it became pretty much stable. I ran these benchmark to see if we can put under more traffic.

@garytong
Copy link

👍 thank you @sinasalek

@matyhtf
Copy link

matyhtf commented Feb 5, 2017

Try swoole extension.

  • Ubuntu 16.04 LTS
  • Intel® Core™ i5-4590 CPU @ 3.30GHz × 4
  • 16G Memory
<?php
$http = new swoole_http_server("127.0.0.1", 1337, SWOOLE_BASE);

$http->set([
    'worker_num' => 4,
]);

$data = [
  'code' => 'ok',
  'error' => false,
  'payload' => 'Hello World'
];

$http->on('request', function ($request, swoole_http_response $response)  use($data)  {
    $response->header('Content-Type', 'application/json');   
    $response->end(json_encode($data));
});

$http->start();

Node.js v4.2.6

wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.08ms    2.70ms 237.82ms   90.94%
    Req/Sec     6.05k   510.34     7.10k    91.00%
  240668 requests in 10.02s, 46.36MB read
Requests/sec:  24026.00
Transfer/sec:      4.63MB

PHP7.1+Swoole-v1.9.5

wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.46ms    1.42ms  27.96ms   85.66%
    Req/Sec    75.29k    36.43k  183.55k    72.75%
  3007806 requests in 10.06s, 605.25MB read
Requests/sec: 299103.32
Transfer/sec:     60.19MB

@alozytskyi
Copy link

@matyhtf is it stable enough for production use? Because those numbers look amazing.

@morozovsk
Copy link

👍 thank you @matyhtf

@mindplay-dk
Copy link

@alozytskyi the swoole homepage says "production ready" :-)

@sinasalek
Copy link

@matyhtf That's an impressive result, but it seems unfair. nodejs uses single thread but swoole seems to use workers. You should have ru nodejs tests on nodejs pm2 with 4 workers

@sinasalek
Copy link

sinasalek commented Nov 21, 2017

Using swoole extension
CentOS 7 64bit
8GB Memory
24 Cores
Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz

NodeJs 6.9.1

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 51.54ms 16.25ms 405.62ms 97.02%
Req/Sec 1.83k 469.94 2.36k 86.93%
72664 requests in 10.01s, 14.00MB read
Requests/sec: 7256.23
Transfer/sec: 1.40MB

NodeJs 9

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 44.86ms 17.73ms 367.20ms 87.05%
Req/Sec 2.09k 621.34 2.96k 76.75%
83419 requests in 10.03s, 12.25MB read
Requests/sec: 8314.27
Transfer/sec: 1.22MB

NodeJs 9+ Cluster with 4 Cores

wrk -t4 -c400 -d10s http://127.0.0.1:1337/
Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 17.75ms 56.01ms 811.30ms 97.51%
Req/Sec 9.64k 2.14k 11.16k 88.50%
384055 requests in 10.01s, 52.74MB read
Requests/sec: 38361.77
Transfer/sec: 5.27MB

PHP7.1+Swoole-v1.9.22

Running 10s test @ http://127.0.0.1:1337/
4 threads and 400 connections

Thread Stats Avg Stdev Max +/- Stdev
Latency 3.56ms 2.95ms 218.94ms 98.04%
Req/Sec 27.80k 4.73k 37.95k 87.00%
1108229 requests in 10.03s, 223.00MB read
Requests/sec: 110515.99
Transfer/sec: 22.24MB

NodeJS Cluster Code used for benchmark

var cluster = require('cluster');
var http = require('http');
var numCPUs = 4;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(1337);
}

@kkumar326
Copy link

Are these swoole stats real? It looks unreal.

@subpardaemon
Copy link

holy crap, those numbers with swoole!

but this is just raw socket in&out numbers, wonder what would happen if we added some meaningful functionality into it, like querying a mysql server or a redis instance. anyone want to create a test like that?

@ifubar
Copy link

ifubar commented Jan 26, 2018

@sinasalek
Is Swoole used all 24 cpu cores and node cluster 4 only?

@d4wae89d498
Copy link

d4wae89d498 commented Jan 26, 2018

See more swoole benchmark here : https://github.com/MarcFaussurier/PHP-swoole-vs-NodeJS-benchmark/blob/master/Swoole_VS_Node.md

I had about 160 MB / SEC with stable releases

@bawasaab
Copy link

try reactphp
https://reactphp.org/

@embluk
Copy link

embluk commented Feb 1, 2018

How real are these Swoole benchmarks and is ReactPHP falling behind because it is a pure PHP implementation and Swoole is using C/C++?

@MarcFaussurier How come the PHP 7.3 benchmark with JIT enabled is much slower than 1st place? Is it because the JIT is in development still?

@robertkraig
Copy link

@MarcFaussurier how does that compare with the newest version of nodejs?

@Wulfklaue
Copy link

Wulfklaue commented Feb 17, 2018

Here are some of my results:

Windows 10 64Bit
32GB 2400 ECC Memory
i5 6 Cores @ 4.7Ghz. No HT!

Results:

NodeJS ( Windows Root - Without Cluster ):

14,930.33 [#/sec] (mean) ( maxing 50% CPU usage )

NodeJS ( Windows Root - With Cluster 6 threads = match CPU ):

14.999.51 [#/sec] (mean) ( maxing 55% CPU usage ) << Seem hitting a wall somewhere

Crystal ( WSL )

80,306.77 [#/sec] (mean) ( maxing 65% CPU usage )

Swoole + PHP 7.0 ( WSL ... Automatic 8 threads active ) :

111,661.30 [#/sec] (mean) ( 99% CPU usage )

Go ( WSL ):

138,823.71 [#/sec] (mean) ( 99% CPU usage )

Go ( Windows Root):

196,741.68 [#/sec] (mean) ( 99% CPU usage )

Note: Apache Bench is eating almost 10 a 20%...

WSL:

As you can tell from the Go tests, WSL eats a heft chunk of performance. But even with the performance degradation Swoole+PHP is still 8 Times faster.

Node

While yes, NodeJS was only hitting 50% CPU usage, it had access to the pure Windows Root. As we see with the Go benchmarks, WSL easily eats 1/3 performance. For some reason NodeJS in cluster mod was still being limited. Tried NodeJS under WSL = Socket issues.

Careful

But Swoole has a few points you need to be careful about. I noticed massive memory leaks from a custom framework until i figure out its because PHP did not properly clean up in specific situations.

For instance, do NOT use: register_shutdown_function, set_error_handler, set_exception_handler and self registering classes. Avoid global (always a good tip).

Unfortunately the link is in Chinese because well ... the Swoole developers are Chinese. Also part of the reason why few people know it in the West.

Link to Chinese Google translated Docs

@embluk

Swoole is using C if i remember correctly. And those results are real... I have done my own simple "hello world" benchmarks, benchmarks with my custom framework from work ( see below ) and with some preliminary database access. Because i am lazy and run this under Windows Linux layer, it also affect performance but even then Swoole kicks ass.

@subpardaemon:

I tried under Windows WSL using Sqlite ( connect, create table if not exist, insert values, read values ) with a in-memory database ( because WSL file access is horrible slow ) and i was hitting 38.000 req / second with ease. And that is with the default PHP Sqlite driver. It has no aync support as the Mysql driver that Swoole has included.

My custom framework ( that leaked memory because of the issues mentioned above ) without database access ( routing, Dependency injection, logging, and lots of other activity ) was doing 103K req/sec. So almost no slowdown compared to raw Hello World.

And this framework was simply quickly stripped of DB access ( because WSL is so slow for file access, i did not want to contaminate the results ), its a actual production Rest framework that i use at work. Its technically not Swoole idiomatic designed. The whole rooting i can fall back on Swoole for that. I "cheated" by:

    $_SERVER['REQUEST_URI'] = $request->server[ 'request_uri' ];
    $_SERVER['REQUEST_METHOD'] = $request->server[ 'request_method' ];
    $_SERVER['REMOTE_ADDR'] = $request->server[ 'remote_addr' ];

Because Swoole by itself does not fill up that data.

Conclusion:

Its a impressive piece of tech, allowing a person to run PHP almost at full blown compiled language speeds. With some precautions how you program.

How tested is it? Well, i know that Tencent uses it. Tencent = WeChat ... The Chinese equivalent of WhatApp.

https://github.com/Tencent/tsf

Going to do more testing but i frankly think this is the direction that PHP needs to go, if they want to stay relevant in the future. Optimize PHP, not unloading PHP after each request, fix the memory issues. Its especially that last part, what is massive killing most scripting languages their performance, the fresh start with each request. And the IO blocking.

I know that PHP 8.0 has a JIT experimental engine but its simply the wrong direction. Do not try to speed up the loading, prevent the unloading and blocking issues.

@d4wae89d498
Copy link

@embluk Yes thats it, JIT is purely for development purpose for now and it still doesn't bring any performances gain yet, but it looks pretty nice for a "master" branch ! I'm sure that the production release will be amazing.

@robertkraig I will test with nodejs 9 once i'll get at home ;)

@RWOverdijk
Copy link

Thanks for sharing all the results. It's really interesting.

@sinasalek
Copy link

@ifubar They both used the same number of CPU cores. Also note that raw swoole performance is in pair with nginx!! i couldn't believe it but i ran it several times and the result was consistent! Also note that in real world applications the difference is much less but nonetheless it proves that php can now be used even as a static file server!

@bawasaab
Copy link

@arunnabraham
Copy link

checkout the below one

https://medium.com/@mtrdesign/reactphp-6c65735138a0

https://reactphp.org/

React is good but no where near fast as Swoole

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment