As the RFC said.
https://wiki.php.net/rfc/generator-delegation
The defining feature of Generator functions is their support for
suspending execution for later resumption. This capability gives
applications a mechanism to implement asynchronous and concurrent
architectures even in a traditionally single-threaded language like
PHP. With simple userland task scheduling systems interleaved
generators become lightweight threads of execution for concurrent
processing tasks.
I wrote a small test. to see if it really concurrent processing any tasks.
the result looks bad. Still single blocking thread.
<?php
function delayYield()
{
$delay = mt_rand(1, 5);
echo "Delay $delay seconds" . PHP_EOL;
sleep($delay);
yield date('Y-m-d H:i:s');
}
function demoYield()
{
yield from delayYield();
yield from delayYield();
yield from delayYield();
return delayYield();
}
foreach (demoYield() as $v) {
echo $v . PHP_EOL;
}
the executed result:
Delay 3 seconds
2015-12-07 07:04:12
Delay 4 seconds
2015-12-07 07:04:16
Delay 1 seconds
2015-12-07 07:04:17
What is concurrent processing as you know?
http://docs.hhvm.com/hack/async/introduction
HHVM async described well .
Appreciate your time.
Netroby
Netroby wrote on 07/12/2015 07:05:
As the RFC said.
https://wiki.php.net/rfc/generator-delegation
The defining feature of Generator functions is their support for
suspending execution for later resumption. This capability gives
applications a mechanism to implement asynchronous and concurrent
architectures even in a traditionally single-threaded language like
PHP. With simple userland task scheduling systems interleaved
generators become lightweight threads of execution for concurrent
processing tasks.I wrote a small test. to see if it really concurrent processing any tasks.
the result looks bad. Still single blocking thread.
You might be interested in this recent thread:
http://marc.info/?t=144342922700001&r=1&w=2 Particularly the discussion
of parallel vs asynchronous execution here:
http://marc.info/?l=php-internals&m=144354107223549&w=2
Generators / co-routines can be useful when working with asynchronous
APIs - that is, functions which start a background task and notify when
it is completed - but they do not magically make sequential code
parallelizable. Threads - true parallel execution - are much more
complex to implement, because of the need to access shared resources in
a safe way.
So there is nothing surprising in your example not running in parallel:
"yield" does not start a new thread, and "sleep" is not an asynchronous
API. If instead of sleep you called an asynchronous function, such as a
MySQL call set to asynchronous mode, you would indeed see your
co-routines running concurrently, as each waited for its respective
query result to come back from the database.
Hope that helps point you in the right direction to better understand
what's going on.
Regards,
Rowan Collins
[IMSoP]
Hi Netroby,
I wrote a small test. to see if it really concurrent processing any tasks.
the result looks bad. Still single blocking thread.
As the RFC already states:
The actual implementation of coroutine task schedulers is outside the scope
of this document. This RFC focuses only on the language-level machinery
needed to make such tools more feasible in userland. It should be obvious
that simply moving code into a generator function will not somehow make it
magically concurrent.
You need a task scheduler like Amp (https://github.com/amphp/amp).
With Amp, you code would look like:
<?php
function delayYield() {
$delay = mt_rand(1, 5);
echo "Delay $delay seconds" . PHP_EOL;
yield new Amp\Pause($delay * 1000); // <-- Note: It's not using a
synchrnous sleep here!
return date('Y-m-d H:i:s');
}Amp\run(function() {
$promises = [];
for ($i = 0; $i < 3; $i++) {
$promises[] = Amp\resolve(delayYield()); // turns the generator
into a promise so they're combinable with Amp\all
}
$dates = yield Amp\all($promises);
});
yield from is more to factor larger functions into smaller units than
directly for doing tasks asynchronously.
Regards, Niklas