While trying to debug php-pm/php-pm#456 I noticed that during high concurrency tests (-c 100) some of the TCP streams where reset and failed. I ended up testing the simplest reactphp http server to reproduce it and compare it with the simplest nodejs server. For the tests, I used the libuv event loop, but it also happens with the StreamSelect loop.
reactphp
<?php
include __DIR__.'/vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) {
return new React\Http\Response(
200,
array('Content-Type' => 'text/plain'),
"Hello World!\n"
);
});
$socket = new React\Socket\Server(8080, $loop);
$server->listen($socket);
echo "Server running at http://127.0.0.1:8080\n";
$loop->run();
nodejs
const http = require('http')
const requestHandler = (request, response) => {
response.end('Hello World!')
}
const server = http.createServer(requestHandler)
server.listen(8080, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log('Server running at http://127.0.0.1:8080')
})
Benchmarked using https://github.com/rakyll/hey, but the resets also occur using ab
hey -n 100 -c 100 http://127.0.0.1:8080/
reactphp
Summary:
Total: 0.2094 secs
Slowest: 0.2055 secs
Fastest: 0.0207 secs
Average: 0.0767 secs
Requests/sec: 477.4997
Total data: 988 bytes
Size/request: 13 bytes
Response time histogram:
0.021 [1] |■
0.039 [32] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.058 [0] |
0.076 [0] |
0.095 [0] |
0.113 [37] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.132 [2] |■■
0.150 [0] |
0.169 [0] |
0.187 [0] |
0.205 [4] |■■■■
Latency distribution:
10% in 0.0227 secs
25% in 0.0239 secs
50% in 0.1051 secs
75% in 0.1099 secs
90% in 0.1122 secs
95% in 0.2047 secs
0% in 0.0000 secs
Details (average, fastest, slowest):
DNS+dialup: 0.0637 secs, 0.0207 secs, 0.2055 secs
DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs
req write: 0.0002 secs, 0.0000 secs, 0.0006 secs
resp wait: 0.0127 secs, 0.0004 secs, 0.0252 secs
resp read: 0.0000 secs, 0.0000 secs, 0.0002 secs
Status code distribution:
[200] 76 responses
Error distribution:
[17] Get http://127.0.0.1:8080/: dial tcp 127.0.0.1:8080: connect: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57270->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57303->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57307->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57308->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57309->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57323->127.0.0.1:8080: read: connection reset by peer
[1] Get http://127.0.0.1:8080/: read tcp 127.0.0.1:57325->127.0.0.1:8080: read: connection reset by peer
nodejs
Summary:
Total: 0.0574 secs
Slowest: 0.0393 secs
Fastest: 0.0176 secs
Average: 0.0303 secs
Requests/sec: 1740.8161
Total data: 1200 bytes
Size/request: 12 bytes
Response time histogram:
0.018 [1] |■
0.020 [3] |■■■■
0.022 [0] |
0.024 [6] |■■■■■■■■
0.026 [19] |■■■■■■■■■■■■■■■■■■■■■■■■■
0.028 [29] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.031 [1] |■
0.033 [2] |■■■
0.035 [2] |■■■
0.037 [6] |■■■■■■■■
0.039 [31] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Latency distribution:
10% in 0.0244 secs
25% in 0.0257 secs
50% in 0.0276 secs
75% in 0.0376 secs
90% in 0.0381 secs
95% in 0.0384 secs
99% in 0.0393 secs
Details (average, fastest, slowest):
DNS+dialup: 0.0032 secs, 0.0176 secs, 0.0393 secs
DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs
req write: 0.0001 secs, 0.0000 secs, 0.0033 secs
resp wait: 0.0262 secs, 0.0076 secs, 0.0389 secs
resp read: 0.0001 secs, 0.0000 secs, 0.0013 secs
Status code distribution:
[200] 100 responses
Not sure what could be the culprit here, is this a php streams issue? Or is reactphp somehow inadvertently causing those TCP resets?
Here are the TCP dumps
tcpdump.zip
PS: Besides the TCP resets, the reactphp histogram is also pretty weird, with some requests being very fast, but others being considerably slower. nodejs performance is much more consistent
While trying to debug php-pm/php-pm#456 I noticed that during high concurrency tests (-c 100) some of the TCP streams where reset and failed. I ended up testing the simplest reactphp http server to reproduce it and compare it with the simplest nodejs server. For the tests, I used the
libuvevent loop, but it also happens with theStreamSelectloop.reactphp
nodejs
Benchmarked using https://github.com/rakyll/hey, but the resets also occur using
abhey -n 100 -c 100 http://127.0.0.1:8080/reactphp
nodejs
Not sure what could be the culprit here, is this a php streams issue? Or is reactphp somehow inadvertently causing those TCP resets?
Here are the TCP dumps
tcpdump.zip
PS: Besides the TCP resets, the reactphp histogram is also pretty weird, with some requests being very fast, but others being considerably slower. nodejs performance is much more consistent