> 2021年3月10日 上午2:58,Aaron Piotrowski <aa...@trowski.com> 写道: > > >> On Mar 8, 2021, at 1:40 PM, Aaron Piotrowski <aa...@trowski.com> 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