Closed idealogica closed 3 years ago
However, I noticed that the following code outputs both 'before timeout' and 'after timeout'
go(function () {
$nextTime = time() + 5;
while (1) {
if (time() >= $nextTime) {
$nextTime = time() + 5;
go(function () {
dump('before timeout');
\Co\System::sleep(2);
dump('after timeout');
});
}
$this->client->recv();
\Co\System::sleep(0.1);
}
});
Would you please explain what's happening? Can I call recv() in the loop without sleeping?
Newbie here, so hopefully this isn't bogus advice, but I ran into a similar issue, check out WaitGroup. Also, I think you have to surround the whole thing by \Co\Run (as opposed to Go). Maybe something like this?
// Psuedocode
\Co\run(function() {
$wg = new Swoole\Coroutine\WaitGroup();
for($loop = 1; $loop <= 5; $loop++) {
go(function() {
try {
$wg->add();
Co::sleep($loop);
echo "Done $loop\n";
} catch($e) {
echo "Error: " . $e->getMessage();
} finally {
$wg->done();
}
});
}
$wg->wait(10000); // wait for max 10 sec timeout
});
https://www.swoole.co.uk/docs/modules/swoole-coroutine-waitgroup
Thank you for the answer, but I'm not sure I understand it. I don't need to sync coroutines. I just need \Co\System::sleep(2);
to finish sleeping every 7 seconds so it outputs "after timeout" string without placing additional \Co\System::sleep(0.1);
call in the loop.
Also when I call Co\run() it shows the warning Swoole\Coroutine\Scheduler::start(): eventLoop has already been created. unable to start Swoole\Coroutine\Scheduler in @swoole-src/library/alias_ns.php on line 17
$this->client->recv();
Is it blocking io, or is there an infinite loop ?
It's blocking this coroutine:
go(function () {
dump('before timeout');
\Co\System::sleep(2);
dump('after timeout');
});
on this line: \Co\System::sleep(2);
Infinite loop is not a problem.
I'm experiencing the same behaviour where the co::sleep(1) never returns just like @idealogica
` php --ri swoole
swoole
Swoole => enabled Author => Swoole Team team@swoole.com Version => 4.5.8 Built => Nov 21 2020 08:19:29 coroutine => enabled trace_log => enabled epoll => enabled eventfd => enabled signalfd => enabled cpu_affinity => enabled spinlock => enabled rwlock => enabled sockets => enabled openssl => OpenSSL 1.1.1c FIPS 28 May 2019 http2 => enabled json => enabled pcre => enabled zlib => 1.2.11 brotli => E16777222/D16777222 mutex_timedlock => enabled pthread_barrier => enabled futex => enabled mysqlnd => enabled async_redis => enabled
Directive => Local Value => Master Value swoole.enable_coroutine => On => On swoole.enable_library => On => On swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => On => On swoole.unixsock_buffer_size => 8388608 => 8388608 `
\Co::set(['enable_preemptive_scheduler' => true]);
\Co\run(function () {
$nextTime = time() + 5;
while (1) {
if (time() >= $nextTime) {
$nextTime = time() + 5;
go(function () {
var_dump('before timeout');
\Co\System::sleep(1);
var_dump('after timeout');
});
}
}
});
@sy-records Thank you, adding the following did fix my issue.
\Co::set(['enable_preemptive_scheduler' => true]);
Is this a bug that will be fixed or an undocumented feature that will be documented :-)
Thanks again. I never would have known to do that.
This is an option added from v4.4.0.
Added a new Coroutine Preemptive Scheduler to prevent the Coroutine from taking too long CPU time to cause other Coroutine to starve.
Thank you so much for the solution. I was also confused with this, and didn't know that there is a special setting to fix thus issue
@sy-records Is there any enable_preemptive_scheduler
drawbacks? Why isn't it enabled by default? I tried to enable it on production and it looks like it consumed all memory on the servers...
You may need to check the logic of your code.
True, the memory consumption caused by incorrect socket_buffer_size
option value. enable_preemptive_scheduler
works perfectly under load. Thank you for your help. I guess this can be closed now.
Hello dear Swoole developers,
It outputs only 'before timeout', it doesn't output 'after timeout' Server::after() behaves the same
I expected it outputs both 'before timeout' and 'after timeout' strings
It outputs only 'before timeout'
php --ri swoole
)?Thank you for the help!