-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdynamic_level.php
More file actions
109 lines (82 loc) · 2.58 KB
/
dynamic_level.php
File metadata and controls
109 lines (82 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\TransferStats;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;
use function GuzzleHttp\Promise\each_limit;
require __DIR__ . '/../vendor/autoload.php';
class LastResponses
{
private $timeline = [];
private $sorted = [];
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function add($time)
{
array_unshift($this->timeline, $time);
// Maintain only 100 last elements.
$this->sorted = array_slice($this->timeline, 0, 100);
// And keep it sorted, obviously.
sort($this->sorted);
}
public function percentile95()
{
$index = (int) ceil(count($this->sorted) * 0.95);
return $this->sorted[$index];
}
public function concurrencyLevelFn()
{
return function ($currentAmount) {
$threshold = 2;
$min = 3;
$max = 15;
$result = $max;
if ($this->percentile95() >= $threshold) {
$result = $currentAmount >= $min ? $currentAmount : $min;
}
$this->logger->info('New concurrency: ' . $result);
return $result;
};
}
public function onStatFn()
{
return function (TransferStats $stats) {
$this->add($stats->getTransferTime());
};
}
}
$genFn = function (ClientInterface $client, callable $statsFn, LoggerInterface $logger) {
$links = array_fill(0, 100, 'http://www.deelay.me/3000/http://deelay.me/img/1000ms.gif');
foreach ($links as $link) {
$logger->debug('Query placed in the queue...');
yield $client->getAsync($link, ['on_stats' => $statsFn])->then(
function ($result) use ($logger) {
$logger->info('Query completed!');
},
function ($reason) use ($logger) {
$logger->error('Query failed :(');
}
);
}
};
// Logger to show pretty messages with timestamps.
$logger = new Logger('default');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
$responseCollection = new LastResponses($logger);
$stack = HandlerStack::create();
$httpClient = new Client([
'handler' => $stack,
]);
$gen = $genFn($httpClient, $responseCollection->onStatFn(), $logger);
// 2 active + always 2 spare in the queue.
$p = each_limit($gen, $responseCollection->concurrencyLevelFn());
$p->wait();