Skip to content

Instantly share code, notes, and snippets.

@nkt
Last active September 27, 2023 08:24
Show Gist options
  • 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
@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