Good day, everyone.
I would like to request permission to create an RFC dedicated to the
asynchronous module for PHP.
Although the source code development is still in progress, a significant
part of it has already been written, and the initial tests are working
successfully. Therefore, I could start the documentation process if you
consider this topic relevant and interesting for the community.
A brief overview of what this RFC will cover:
-
True asynchronous support for PHP core functions without additional
"tricks." -
Scheduler and Reactor components, providing a C-API for PHP
extensions to enable non-blocking I/O in plugins or core code. - User-Land API that mirrors the C-API for PHP developers.
- Basic primitives for concurrent programming, such as Channel and
Iterator. - Built-in integration with the LibUV library.
The library is based on Fiber, extending and enhancing it to provide PHP
developers with a full set of tools for concurrent applications.
Have a great day!
Edmond
Hi
Good day, everyone.
I would like to request permission to create an RFC dedicated to the
asynchronous module for PHP.
Someone will surely grant you karma soon. RFC makes sense.
Although the source code development is still in progress, a significant
part of it has already been written, and the initial tests are working
successfully. Therefore, I could start the documentation process if you
consider this topic relevant and interesting for the community.
A brief overview of what this RFC will cover:
- True asynchronous support for PHP core functions without
additional "tricks."- Scheduler and Reactor components, providing a C-API for PHP
extensions to enable non-blocking I/O in plugins or core code.- User-Land API that mirrors the C-API for PHP developers.
- Basic primitives for concurrent programming, such as Channel and
Iterator.- Built-in integration with the LibUV library.
The library is based on Fiber, extending and enhancing it to provide
PHP developers with a full set of tools for concurrent applications.
Looks interesting. I understand that's not ready for review yet but quickly
checked the code anyway. Is there some particular reason why this is not an
extension? Think it might actually make sense to split it to two extensions
- one for the core main stuff (that could be enabled by default) and then
libuv optional part - similar to pdo for example. I haven't checked too
deeply the code though so I might be missing things. Feel free to create a
draft PR even if it's not ready. It might help to get some initial
pre-reviews... :)
Regards
Jakub
A brief overview of what this RFC will cover:
- True asynchronous support for PHP core functions without
additional "tricks."- Scheduler and Reactor components, providing a C-API for PHP
extensions to enable non-blocking I/O in plugins or core code.- User-Land API that mirrors the C-API for PHP developers.
- Basic primitives for concurrent programming, such as Channel and
Iterator.- Built-in integration with the LibUV library.
The library is based on Fiber, extending and enhancing it to provide
PHP developers with a full set of tools for concurrent applications.Looks interesting. I understand that's not ready for review yet but
quickly checked the code anyway. Is there some particular reason why this
is not an extension? Think it might actually make sense to split it to two
extensions - one for the core main stuff (that could be enabled by default)
and then libuv optional part - similar to pdo for example. I haven't
checked too deeply the code though so I might be missing things. Feel free
to create a draft PR even if it's not ready. It might help to get some
initial pre-reviews... :)
In terms of RFC, it would be good to also compare it with alternatives.
From a quick look it slightly reminded me swow (
https://github.com/swow/swow ) but I didn't really look that deeply into it
and I also don't know that much about swow so might be wrong.
I would like to request permission to create an RFC dedicated to the
asynchronous module for PHP.
Have you already registered a new Wiki user? If so, what's your
username? Otherwise head over to https://wiki.php.net/?do=register.
Christoph
Good day, everyone.
I would like to request permission to create an RFC dedicated to the
asynchronous module for PHP.Although the source code development is still in progress, a
significant part of it has already been written, and the initial tests
are working successfully. Therefore, I could start the documentation
process if you consider this topic relevant and interesting for the
community.A brief overview of what this RFC will cover:
- True asynchronous support for PHP core functions without
additional "tricks."- Scheduler and Reactor components, providing a C-API for PHP
extensions to enable non-blocking I/O in plugins or core code.- User-Land API that mirrors the C-API for PHP developers.
- Basic primitives for concurrent programming, such as Channel and
Iterator.- Built-in integration with the LibUV library.
The library is based on Fiber, extending and enhancing it to provide
PHP developers with a full set of tools for concurrent applications.Have a great day!
Edmond
Is it really necessary to have all these Async\launchScheduler();
calls? Why can't the scheduler always be running, the same as it is in
JavaScript or any other async language? Even (userland) Revolt does not
require the event loop to be manually started.
Cheers,
Bilge
Hello Bilge!
Is it really necessary to have all these
Async\launchScheduler();
calls? Why can't the scheduler always be running, the same as it is in
JavaScript or any other async language? Even (userland) Revolt does not
require the event loop to be manually started.
Short answer: This implementation is simpler — not so much in terms of
code size but in terms of reducing сonfusion. And we achieve a consistent
state when asynchronous code runs within a Fiber, rather than having a
situation where we are in a Fiber here but not there.
For example, consider how the Fiber switching mechanism works in PHP. If
FiberB is launched from FiberA, FiberB can only return to FiberA.
Consequently, if the Scheduler component is placed inside a Fiber, the code
must track the "direction" of switching.
Running the Scheduler in the "zero" Fiber results in the simplest possible
switching logic. It also defines a clear point where exceptions can be
thrown.
One might argue that no other language does it this way. But then, no other
language has Fiber as a low-level tool (except C). From this perspective,
explicit activation of the Scheduler aligns with Fiber as a low-level
construct.
Can this be avoided? Yes, but such alternative approaches often rely
on implicit
behavior. And implicit behavior tends to break things.
Of course, we could start the code inside a Fiber to initialize the
Scheduler and hide the implementation, but again, that's not always
necessary or useful for everyone.
Ed.
I forgot to mention this. There is an important limitation in how this
solution behaves in the context of PHP.
Calls to PHP functions that normally block execution in the zero-Fiber do
not change their behavior. This solution has both advantages and
disadvantages. The advantage is that it does not break backward
compatibility in any way. Calling sleep(10) at the beginning of <?php will
cause the process to go into a wait state.
True Async changes the behavior of functions only if they are running
inside a Fiber with an active Scheduler.
This is yet another consequence of this architectural decision, and some
people might not like it. However, at this point, I don’t see a better
solution that would be optimally balanced between legacy support, explicit
behavior, and implementation simplicity.
Have a nice day!
Ed.
I forgot to mention this. There is an important limitation in how
this solution behaves in the context of PHP.Calls to PHP functions that normally block execution in the zero-Fiber
do not change their behavior. This solution has both advantages and
disadvantages. The advantage is that it does not break backward
compatibility in any way. Calling |sleep(10)| at the beginning of
|<?php| will cause the process to go into a wait state.True Async changes the behavior of functions only if they are
running inside a Fiber with an active Scheduler.This is yet another consequence of this architectural decision, and
some people might not like it. However, at this point, I don’t see a
better solution that would be optimally balanced between legacy
support, explicit behavior, and implementation simplicity.Have a nice day!
Ed.
There should be no perceptible difference between a blocking sleep(10)
and an async sleep(10), so what backwards compatibility are you
referring to?
Bilge
There should be no perceptible difference between a blocking sleep(10)
and an async sleep(10), so what backwards compatibility are you referring
to?
For example, the behavior of the code below will not change. The code will
execute sequentially, and context switching will only occur when resume/
suspend is called.
However, when the Scheduler is activated, this behavior changes. Now,
calling sleep()
inside a Fiber will lead to a context switch.
If the activation of the Scheduler is implicit, previously written code may
not work as the developer expects.
<?php
$fiber = new Fiber(function (): void {
echo "Start fiber\n";
sleep(1);
Fiber::suspend("Paused");
echo "Resume fiber\n";
});
$result = $fiber->start();
echo "Fiber suspended with: $result\n";
sleep(10);
$fiber->resume();
echo "Fiber finished\n";
There should be no perceptible difference between a blocking sleep(10) and an async sleep(10), so what backwards compatibility are you referring to?
For example, the behavior of the code below will not change. The code will execute sequentially, and context switching will only occur when
resume
/suspend
is called.However, when the
Scheduler
is activated, this behavior changes. Now, callingsleep()
inside aFiber
will lead to a context switch.If the activation of the
Scheduler
is implicit, previously written code may not work as the developer expects.<?php
$fiber = new Fiber(function (): void {
echo "Start fiber\n";
sleep(1);
Fiber::suspend("Paused");
echo "Resume fiber\n";
});$result = $fiber->start();
echo "Fiber suspended with: $result\n";
sleep(10);
$fiber->resume();
echo "Fiber finished\n";
I think what bilge was trying to point out is that there should be absolutely no change on existing software with or without the scheduler running (for software not using fibers).
— Rob
I think what bilge was trying to point out is that there should be
absolutely no change on existing software with or without the scheduler
running (for software not using fibers).
I thought the same. But where would you hide Fibers? They are part of the
language.
The existence of Fibers is an unpleasant issue in the context of language
design. Essentially, they break the integrity of the implementation by
creating a "backdoor" for user-land.
So... various ways can be devised to disguise this fact, but they will all
have drawbacks.
Of course, you can create the Scheduler before starting the script and run
the script inside a Fiber. But I'm sure there will be someone who will say
they don't like this approach.
Ed.