function gRange($min, $max, $step): \Generator { for ($i = $min; $i < $max; $i += $step) { yield $i; } } foreach (gRange(12, 82, 5) as $n) { echo "$n\n"; // 12, 17, 22, etc. }
function spooky(): \Generator { while (true) { yield random_int(0, 1) ? 'O' : 'o'; } } foreach (spooky() as $chr) { echo $chr; usleep(100000); }
If you call a function that yields, you will not execute that function. You'll get back a Generator object. To execute the function, you need to call methods on the Generator.
Also, "return" means something different for a Generator than for a normal function.
$g = gen(1);
$a = $g->current();
2
$b = yield $arg1 + 1;
$c = $g->send($a + 1);
$d = yield $b + 2;
5
3
function gen($arg1)
$e = $g->send($c + 1);
6
return $d + 2;
null
echo $g->getReturn();
8
* Ignoring curl_multi and wrappers (e.g. Guzzle)
With generator-based concurrency, you're trading flexibility in defining concurrency for clarity in defining your task.
var_dump(is_12_factor()); // bool(true)
* Throwables to the rescue!
** amphp/cluster to the rescue!
siege -c 15 -t 30S -b <url> <cookie header>
Transactions: 3616 hits Availability: 100.00 % Elapsed time: 29.19 secs Data transferred: 0.14 MB Response time: 0.12 secs Transaction rate: 123.88 trans/sec Throughput: 0.00 MB/sec Concurrency: 14.96 Successful transactions: 3616 Failed transactions: 0 Longest transaction: 0.25 Shortest transaction: 0.02
~28MB RAM, ~190% CPU
Transactions: 8767 hits Availability: 100.00 % Elapsed time: 29.24 secs Data transferred: 0.33 MB Response time: 0.05 secs Transaction rate: 299.83 trans/sec Throughput: 0.01 MB/sec Concurrency: 14.99 Successful transactions: 8767 Failed transactions: 0 Longest transaction: 0.16 Shortest transaction: 0.00
~30MB RAM, ~80% CPU