Skip to content

Commit 5c952be

Browse files
committed
Add benchmarking example
1 parent 8556c38 commit 5c952be

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

examples/99-benchmark-download.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
// $ php examples/99-benchmark-download.php 8080
4+
// $ curl http://localhost:8080/10g.bin > /dev/null
5+
// $ wget http://localhost:8080/10g.bin -O /dev/null
6+
// $ ab -n10 -c10 http://localhost:8080/1g.bin
7+
// $ docker run -it --rm --net=host jordi/ab ab -n10 -c10 http://localhost:8080/1g.bin
8+
9+
use React\EventLoop\Factory;
10+
use React\Socket\Server;
11+
use React\Http\Response;
12+
use Psr\Http\Message\RequestInterface;
13+
use React\Stream\ReadableStream;
14+
15+
require __DIR__ . '/../vendor/autoload.php';
16+
17+
$loop = Factory::create();
18+
$socket = new Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop);
19+
20+
/** A readable stream that can emit a lot of data */
21+
class ChunkRepeater extends ReadableStream
22+
{
23+
private $chunk;
24+
private $count;
25+
private $position = 0;
26+
private $paused = true;
27+
28+
public function __construct($chunk, $count)
29+
{
30+
$this->chunk = $chunk;
31+
$this->count = $count;
32+
}
33+
34+
public function pause()
35+
{
36+
$this->paused = true;
37+
}
38+
39+
public function resume()
40+
{
41+
if (!$this->paused) {
42+
return;
43+
}
44+
45+
// keep emitting until stream is paused
46+
$this->paused = false;
47+
while ($this->position < $this->count && !$this->paused) {
48+
++$this->position;
49+
$this->emit('data', array($this->chunk));
50+
}
51+
52+
// end once the last chunk has been written
53+
if ($this->position >= $this->count) {
54+
$this->emit('end');
55+
$this->close();
56+
}
57+
}
58+
59+
public function getSize()
60+
{
61+
return strlen($this->chunk) * $this->count;
62+
}
63+
}
64+
65+
$server = new \React\Http\Server($socket, function (RequestInterface $request) use ($loop) {
66+
switch ($request->getUri()->getPath()) {
67+
case '/':
68+
return new Response(
69+
200,
70+
array('Content-Type' => 'text/html'),
71+
'<html><a href="1g.bin">1g.bin</a><br/><a href="10g.bin">10g.bin</a></html>'
72+
);
73+
case '/1g.bin':
74+
$stream = new ChunkRepeater(str_repeat('.', 1000000), 1000);
75+
break;
76+
case '/10g.bin':
77+
$stream = new ChunkRepeater(str_repeat('.', 1000000), 10000);
78+
break;
79+
default:
80+
return new Response(404);
81+
}
82+
83+
$loop->addTimer(0, array($stream, 'resume'));
84+
85+
return new Response(
86+
200,
87+
array('Content-Type' => 'application/octet-data', 'Content-Length' => $stream->getSize()),
88+
$stream
89+
);
90+
});
91+
92+
echo 'Listening on http://' . $socket->getAddress() . PHP_EOL;
93+
94+
$loop->run();

0 commit comments

Comments
 (0)