> 2021年3月10日 上午2:58,Aaron Piotrowski <[email protected]> 写道:
>
>
>> On Mar 8, 2021, at 1:40 PM, Aaron Piotrowski <[email protected]> wrote:
>>
>> Greetings everyone!
>>
>> The vote has started on the fiber RFC: https://wiki.php.net/rfc/fibers
>> <https://wiki.php.net/rfc/fibers>
>>
>> Voting will run through March 22nd.
>>
>> Cheers,
>> Aaron Piotrowski
>
> Hi all!
>
> A concern was raised off list that due to the complexity of the way this
> feature interacts with the engine, it may be best to mark the feature as
> experimental. This would allow some changes to be made to certain edge-case
> behaviors and, while I don't think it would be necessary, the public API.
>
> We (Niklas and I) agree with this and propose that if this feature is
> accepted, it is marked as experimental through the 8.x release cycle or until
> we're comfortable removing that label, whichever comes first.
>
> Experimental in this context would mean fibers would be compiled and
> available in all releases, but the documentation would denote that behavioral
> and API changes may be made in future minor releases – use at your own risk.
>
> As this feature is targeted at library authors and not average PHP users, we
> believe there would be little effect to the community to take this step.
>
> Cheers,
> Aaron Piotrowski
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
Sorry for being late, writing an English manuscript is still a bit difficult
for me. Here I want to continue to express some of my views.
Firstly, I want to emphasize that the separate Fiber API has no meaning to
users. Many people have a misunderstanding about this. They think that the
Fiber feature can make PHP have the same high-performance network programming
capabilities as Golang and support it blindly. There is a complete and complex
system behind Goroutine. In terms of the amount of work implemented, the
context switching capability, which is the capability provided by the ext-fiber
extension, is only a very insignificant part.
In my opinion, Fiber is just an enhancement of Generator. As far as my
superficial understanding is concerned, the evolution direction of amphp and
reactphp should be similar to that of node.js. And node.js is not implemented
with on any stacked-coroutines. In theory, the performance of
stackless-coroutine is better. Furthermore, the implementation of await/async
does not require stacked-coroutine. Therefore, I'm confused about the content
of the Fiber proposal, because, it seems to put it in the wrong direction.
The implementation of the coroutine and the entire system are complementary and
inseparable. With the optimization and update of the entire system, there will
be more and more customization requirements, which influence the implementation
details of the coroutine. This is also the reason why Swoole did not merge its
coroutine capabilities into php-src, individually. As stripping out a separate
coroutine extension, many customized things will lose their reason for
existence. Therefore, we hope to incorporate the entire system, which will make
everything more logical.
As Nikita said, if it is unnecessary, it is better to let the expansion stay in
PECL, which will bring more freedom to the project and be more conducive to the
rapid development of the project. Swoole has mastered all the technologies
applied to ext-fiber in 2018 and built a complete network programming system
based on coroutine. Since then, in order to better integrate with the original
ecosystem of PHP, Swoole has coroutinefied PDO, mysqli, phpredis, libcurl,
etc., and applied them to a large number of real-world projects. These projects
also contributed to the development of the PHP coroutine technology and
ecosystem. Of course, the Swoole community still expects to merge it into
php-src at an appropriate time.
Therefore, I have to point out that there is no practical experience in the
design of ext-fiber. It skips the progress, which to be a PECL extension, and
does not have any guidance of practical application. This is very dangerous.
The proposal regards the PHP kernel as a large test ground in the way that
incorporating Fiber into php-src as an experimental feature. And one of the
main reasons is simply that the installation of extensions is difficult for
some users. For many years, I have always thought that the PHP kernel's
attitude towards merging anything is scientific and rigorous, so I have always
been cautious and respectful. But this time, it makes me confused and a little
bit disappointed.
In various design details, there are still many questions that make me
confused. I will point out a few here:
1. Fiber class should not be designed as final
We should try to avoid any internal class being designed as final unless there
are any necessary security reasons, otherwise, the scalability of the class
will be greatly restricted. For instance, in practice, we usually assign a
Context for every Fiber, it seems like $GLOBALS, so that we can write like this
class MyFiber extends \Fiber {
public $context = [];
}
Or, we can add a custom log for the switch of the coroutine, or switch some
contexts we want to switch
class MyFiber extends \Fiber {
public function resume(...$data):mixed {
log('resume to {$this->getId()}');
return parent::resume($data);
}
}
There are also some coroutine frameworks that want to track and count the
coroutines created by users and will perform some injection operations, so they
have their own special version of the coroutine implementation. If inheritance
is not possible, then we need twice the number of objects, and mounting Fiber
as a property on the newly implemented class. It is bad for performance and
very inelegant.
If ext-fiber is declared as final for technical reasons, then I can only say
that this is a technically problematic implementation.
2. Coroutine state acquisition problem
The ext-fiber defines many methods to obtain the state of the coroutine, such
as isRunning(), etc. Why not directly export the status constants and provide a
getStatus() function, if we just want the simplest implementation?
If there are some internal states on the status, then these states should be
distinguishable. For example, they can be removed by bit operations or stored
on other attributes.
The following are some technical issues about the implementation of ext-fiber.
Due to the limited time, I have only read part of the source code limitedly.
Excuse me, if there are any inaccuracies.
1. The code about coroutine switching could be simplified
There is essentially only one kind of switch API for coroutines that is
resume(), in boost it called jump(). Its function is to switch to a coroutine,
and yield()/suspend() is equivalent to $previousCoroutine->resume(). So I can’t
understand why resume() and suspend() are implemented twice in the
implementation of ext-fiber.
If we indicate the correct implementation of suspend() in PHP, it should look
like this:
public static function suspend(...$data): mixed
{
return static::this()->getPrevious()->resume(...$data);
}
If there are any technical reasons for implementing resume() twice in
ext-fiber, then I can only say that this is still a wrong implementation.
2. Switch notification
In zend_fiber_switch_to(), call zend_observer_fiber_switch_notify() twice at
the beginning and ending of switch is an obviously wrong implementation. After
we solve the previous problem, we only need to notify once before switching,
because the second notification will be sent by another coroutine before it's
switching back.
Other issues
1. C extension support
This Fiber proposal is dedicated to providing PHP with coroutine capabilities,
but it does not consider the C extension. For example, it can consider turning
some APIs into function pointers so that other extensions can add some content.
2. Unsolvable blocking
The Fiber proposal mentions the blocking problem but does not give a good idea
or solution to solve it. In the coroutine system, no blocking is allowed.
Blocking will greatly affect the normal operation of the entire program. Unlike
JavaScript, PHP is not a naturally asynchronous language. Implementing
coroutines and EventLoop in the user space can only solve some blocking from
network calls, but other blocking problems such as file reading and writing,
DNS queries, etc., can hardly be solved. However, PHP is very similar to
node.js, which is more suitable for the 'multi-process with single-thread'
model. Therefore, integrating libuv and tightly combining with coroutine
features to achieve a complete coroutine system is a good asynchronous network
IO solution.
3. CPU starvation
The capability of the 'multi-process with single-thread' model in CPU
scheduling is not that good as Golang's multi-thread model. Solving the CPU
starvation problem is another issue that needs to be considered
For example, in Swow (https://github.com/swow/swow, the latest research result
of the Swoole community), the WatchDog component based on the monitoring the
number of coroutine switching rounds and the interrupt feature of ZendVM solves
this problem. It can issue an alarm when the CPU starvation occurs. Through
configuration or PHP programming, it can also actively suspend the coroutine
when the CPU starvation occurs, restore the average response speed of the
entire program, and even directly kill the coroutine when the CPU infinite loop
occurs.
4. Pure C coroutine
The Fiber proposal never mentions the support for pure C coroutines. In Swow,
the event scheduler is a pure C function and does not need a PHP stack. It only
needs to switch the C stack when switching to other coroutines and its
switching performance is almost double that of PHP, because, in such a
coroutine system, most exchanges occur between the scheduler and other
coroutines.
5. Not compatible with Swoole
In my opinion, Swoole is an important part of the PHP ecosystem. But now, Fiber
cannot work with Swoole. And based on the above reasons, Swoole will not
consider compatible fiber.
We would expect some ZendAPI rather than Fiber extensions to provide support
for coroutine switching.
6. Boost-context is not used on the Windows
The performance of win-fiber is far inferior to boost-context. I can not find
any reason to use win-fiber instead of boost-context in Windows.
The Swow extension uses boost-context on all platforms and has been actively
tested (https://github.com/swow/swow/runs/2053921797). CI will also automate
execute nightly build and release DLL (https://github.com/swow/swow/releases),
and there is no issue so far.
Also, there are many fragmentary issues. Due to limited time, I cannot write
them all at once.
Of course, some designs of ext-fiber still refresh me, such as using Reflection
to get coroutine status (in Swoole, we just keep adding methods to the
coroutine class). Nevertheless, I don’t know what the benefits of using
Reflection to get these states are.
I'm not particularly satisfied with all aspects of ext-fiber's overall plan and
C code implementation, so I have to point them out here.
Regards,
Twosee
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php