Re: [RFC] Fibers
| From: | Aaron Piotrowski | Date: | Fri, 08 Jan 2021 20:47:13 +0000 |
| Subject: | Re: [RFC] Fibers | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-112818@lists.php.net to get a copy of this message | ||
Hi Peter,
> On Jan 8, 2021, at 3:03 AM, Peter Stalman <sarkedev@gmail.com> wrote:
>
> I've been playing around with this for a bit, and I have some more questions. I see you
> recently changed how the
FiberScheduler works, making it
> final and adding some "is" functions to match it more to a
> regular fiber.
>
> Since the FiberScheduler is itself also a fiber, why does it
> need to be a separate class? Why did you choose to go this way and make it "special"
> instead of not just making a regular fiber into a scheduler in userland.
FiberScheduler is “special” because user code is not in control of
suspending/resuming the underlying fiber, so FiberScheduler is a different class from
Fiber without those methods. Internally a user fiber and scheduler fiber are similar,
but I wanted to differentiate them in user code.
FiberScheduler recently changed from an interface to a class because we discovered that
automatically creating a scheduler fiber internally would make it difficult for adaptors or wrappers
of a FiberScheduler to not create multiple internal scheduler fibers when there should
only be a single scheduler fiber. The API largely works the same, but now the creation of the
scheduler fiber is explicit in user code instead of done internally. This way adaptors or wrappers
can return a single FiberScheduler instance. More code is required in user libraries,
but offers greater flexibility.
> Could you have two or more schedulers?
You can have two or more schedulers in a single script. Only one can ever be running at a single
time.
> Could you get by without a scheduler and call a fiber inside a fiber recursively?
This design requires a scheduler fiber to be entered between suspending one user fiber and resume
another user fiber. User fibers are designed to be independent. If two users fibers need to
communicate, they should use something similar to Go’s channels to exchange data.
>
> Related to that, I noticed it was not possible to call
> Fiber::this() from within the scheduler, why is that? Is it not
> just another fiber? Or is this to prevent it from being passed to another scheduler?
A scheduler fiber cannot be suspended or resumed by user code so it is not useful to get a reference
to that fiber.
>
> Alternatively, going the other way, instead of making the scheduler a unique class that needs
> to be passed around, why not go the more "traditional" PHP route and pattern it after
> register_shutdown_function(callable $callback, mixed ...$args) :
> void, spl_autoload_register(callable $autoload_function = ?, bool
> $throw = true, bool $prepend = false) : bool, and those type of functions? After
> all, isn't it just a callback too? Something like
> register_fiber_scheduler(callable $callback) : void?
>
> This would remove the need for a special scheduler class and the need for passing the scheduler
> back to the Fiber::suspend(). Each
> suspend() call would bubble up through the registered scheduler
> callbacks. This would allow competing schedulers to work nicer together, instead of one scheduler
> having to finish before the higher up scheduler can run it's next loop.
The scheduler to be entered is specific to the code calling Fiber::suspend().
Registering a global scheduler would require only a single scheduler to be used in a script. Only a
single scheduler is entered on a call to Fiber::suspend(), not multiple schedulers.
Registering schedulers or wrapping application code in boilerplate depending on the library being
used is something this API is attempting to avoid.
>
> Either way, doesn't the fiber already know which scheduler it is in when it suspends?
No, a fiber can potentially use different schedulers at different suspend points. The scheduler that
starts a fiber does not necessarily need to be the only scheduler that suspends the fiber.
Hopefully that helps in understanding how the API works. Please take a look at how amphp v3 uses
fibers in these examples https://github.com/amphp/amp/tree/v3/examples/pipeline
or in react-fiber https://github.com/trowski/react-fiber/tree/master/examples
where the Fiber API is handled by the library rather than “application” code.
Cheers,
Aaron Piotrowski