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
Greetings everyone!
The vote has started on the fiber RFC: https://wiki.php.net/rfc/fibers
https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron Piotrowski
This is vastly improved from the earlier drafts I saw. Well done, Aaron!
There is one issue that still stands out like a sore thumb to me, which I really should have reviewed and caught earlier. (Entirely my fault.) Fiber::this() seems like a very poorly chosen name for that method. "this" in PHP implies "the object I am currently in." Even if there's no $ on a method, that's still the mental association that word has in PHP. But in this case, Fiber::this() does not mean "the object I'm currently in," but "the Fiber object that wraps the callable I'm currently in, which is itself an object but not the object I mean, but there may be an arbitrary number of call stack levels between me and that Fiber object." That's... very confusing for a human, even if syntactically unambiguous.
I am still voting Yes on the RFC, but I would urge you to follow-up (with another RFC, or a consensus agreement, no one telling you not to, or whatever the process is, I'm easy) with renaming that method to something less confusing. Fiber::active() seems like the best name to me (after some discussion with Aaron off-list), as it refers the fiber that is currently "actively" executing opcodes.
Otherwise, well done and I look forward to when we can build a standardized user-facing API on top of it. :-)
--Larry Garfield
Here we go again! Looking at you, attributes syntax.
Seriously though, any of this
, active
, current
, or even Fiber::self
are fine with me.
You might have the same issue with that last one.
Thanks,
Peter
Greetings everyone!
The vote has started on the fiber RFC: https://wiki.php.net/rfc/fibers
https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron PiotrowskiThis is vastly improved from the earlier drafts I saw. Well done, Aaron!
There is one issue that still stands out like a sore thumb to me, which I
really should have reviewed and caught earlier. (Entirely my fault.)
Fiber::this() seems like a very poorly chosen name for that method. "this"
in PHP implies "the object I am currently in." Even if there's no $ on a
method, that's still the mental association that word has in PHP. But in
this case, Fiber::this() does not mean "the object I'm currently in," but
"the Fiber object that wraps the callable I'm currently in, which is itself
an object but not the object I mean, but there may be an arbitrary number
of call stack levels between me and that Fiber object." That's... very
confusing for a human, even if syntactically unambiguous.I am still voting Yes on the RFC, but I would urge you to follow-up (with
another RFC, or a consensus agreement, no one telling you not to, or
whatever the process is, I'm easy) with renaming that method to something
less confusing. Fiber::active() seems like the best name to me (after some
discussion with Aaron off-list), as it refers the fiber that is currently
"actively" executing opcodes.Otherwise, well done and I look forward to when we can build a
standardized user-facing API on top of it. :-)--Larry Garfield
--
To unsubscribe, visit: https://www.php.net/unsub.php
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
2021年3月10日 上午2:58,Aaron Piotrowski aaron@trowski.com 写道:
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 PiotrowskiHi 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 PiotrowskiTo 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:
- 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.
- 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.
- 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.
- 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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
- 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.
Hi Twosee,
Are you saying that by adding this Fiber code to core it will prevent
Swoole from functioning? If so, that is concerning. Or are you
simply saying that Swoole doesn't like this implementation and will not use
it with their own code?
One thing to consider when comparing the Fiber implementation is that the
vast majority of PHP applications are still run behind a web server in
short-lived requests. Unlike Swoole, Swow, and Parallel, it isn't limited
to ZTS or CLI. It might not be the ideal solution, but IMO it is a step in
the right direction for PHP to allow for better async support.
And I think you are right that "Fiber is just an enhancement of
Generator'', but so what? The Generator addition in 5.5 opened up PHP to a
hacky way of doing async, but it worked everywhere. Fiber allows that to
be much more convenient in switching contexts deep inside a call stack. I
don't think it needs to be the end-all-be-all coroutine solution to rival
Goroutines, and I'm pretty sure it's not trying to be.
Thanks,
Peter
- 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.
Hi Twosee,
Are you saying that by adding this Fiber code to core it will prevent Swoole from functioning? If so, that is concerning. Or are you simply saying that Swoole doesn't like this implementation and will not use it with their own code?
One thing to consider when comparing the Fiber implementation is that the vast majority of PHP applications are still run behind a web server in short-lived requests. Unlike Swoole, Swow, and Parallel, it isn't limited to ZTS or CLI. It might not be the ideal solution, but IMO it is a step in the right direction for PHP to allow for better async support.
And I think you are right that "Fiber is just an enhancement of Generator'', but so what? The Generator addition in 5.5 opened up PHP to a hacky way of doing async, but it worked everywhere. Fiber allows that to be much more convenient in switching contexts deep inside a call stack. I don't think it needs to be the end-all-be-all coroutine solution to rival Goroutines, and I'm pretty sure it's not trying to be.
Thanks,
Peter
Hello,
This Fiber implementation does not conflict with Swoole. Both could coexist. However, Swoole's implementation does provide some other features that this does not, so I believe Twosee was simply saying that Swoole cannot directly use this fiber implementation. My focus was to provide a minimalistic implementation in core so user space code can make other API decisions as they saw fit.
Regarding some of the other concerns raised:
- Switch notification: The observer notification is triggered before switching to a fiber and after suspending from a fiber. The timing here was an open question I've discussed with others and we planned to examine it later. Moving the second notification before suspending the second fiber was already being considered. As this was an internal API I felt it was not needed directly in the RFC.
- Fiber is final, as is Generator. I believe it is better to compose classes rather than extend them. Of course it is always possible to remove final.
- Using Fiber::resume() and Fiber::suspend() models fibers as a stack and simplifies logic of resuming/suspending fibers. Ruby fibers share this exact API, though their API uses the term yield instead of suspend.
- State functions: Separate methods (i.e., isRunning, isTerminated) returning a boolean are preferable IMO to comparing integer constants to a value returned by a status method. This is really a matter of opinion than one being strictly better than the other.
- Pure C coroutine: The extension code provides user space fibers. Adding functions to create fiber C-only fibers can certainly be done if the need arises.
- Being marked experimental: I was hoping this would be a good compromise between allowing people to experiment with fibers and providing the ability to make minor BC breaks if the need arose. I realize this is generally not the PHP way, however this is, IMO, not entirely without precedent. JIT and FFI were not widely used before being added to PHP.
Thanks for the feedback!
Aaron Piotrowski
Hi Twosee, Tianfeng.Han
I was drafting a longer reply to you both, but I realised I might be
missing some information.
Please could you disclose the commercial interests of the Swoole
maintainers, and the ties to the for profit companies that provide
services implementing Swoole?
Having people vote on RFCs who have ties to companies that provide
services via commercial entities isn't unprecedented. For example
zend.com has had employees who are involved in voting on RFCs, but to
a large extent that was done openly, with all of them using zend.com
email addresses.
twosee wrote:
Of course, the Swoole community still expects to merge it into php-src at an appropriate time.
What's your idea of an appropriate time and how do you plan to start
this conversation?
If something hasn't been merged back after 8 years, it sounds
reasonably unlikely that it's ever going to be merged back.
cheers
Dan
Ack
Hi Dan,
We have no commercial purpose on the swoole open source project. This is a purely technical project.
If possible, we can remove the name of swoole, contribute the source code of swoole-src to php-src, and transfer the copyright.
Here is just a technical discussion. My opinion is that if PHP will support fiber/green-threads, this is a major change, should redesign language syntax, standard library, ZendVM.
This proposal must be discussed extensively and in-depth, should not make a hasty decision.
There are 7 parts to consider with my experience:
EventLoop API
Fiber/Coroutine/GreenThread
IO-Scheduler (Socket/FileSystem/ChildProcess/Signal/Timer/Stdout/Stdin)
CPU-Scheduler
Compatible with existing extesions (php_streams/ext-sockets/ext-redis/ext-mysqli/ext-pdo-mysql/ext-curl ...) and builtin-functions (sleep/gethostbyname/proc_open/file_get_contents)
Service container, How to support php-fpm and provide a coroutine version of http server
Coroutine communication, How to pass messages between two coroutines
It’s nice to see php has such topic. This may be the key technology in the next generation of PHP.
Thanks
Tianfeng.Han
------------------ Original ------------------
From: "Dan Ackroyd"<Danack@basereality.com>;
Date: Fri, Mar 12, 2021 05:50 AM
To: "twosee"<twose@qq.com>; "韩天峰"<rango@swoole.com>;
Cc: "Aaron Piotrowski"<aaron@trowski.com>; "php internals"<internals@lists.php.net>;
Subject: Re: [PHP-DEV] [VOTE] Fibers
Hi Twosee, Tianfeng.Han
I was drafting a longer reply to you both, but I realised I might be
missing some information.
Please could you disclose the commercial interests of the Swoole
maintainers, and the ties to the for profit companies that provide
services implementing Swoole?
Having people vote on RFCs who have ties to companies that provide
services via commercial entities isn't unprecedented. For example
zend.com has had employees who are involved in voting on RFCs, but to
a large extent that was done openly, with all of them using zend.com
email addresses.
twosee wrote:
> Of course, the Swoole community still expects to merge it into php-src at an appropriate time.
What's your idea of an appropriate time and how do you plan to start
this conversation?
If something hasn't been merged back after 8 years, it sounds
reasonably unlikely that it's ever going to be merged back.
cheers
Dan
Ack
Hi Dan,
We have no commercial purpose on the swoole open source project. This
is a purely technical project.
If possible, we can remove the name of swoole, contribute the source code
of swoole-src to php-src, and transfer the copyright.
Here is just a technical discussion. My opinion is that if PHP will
support fiber/green-threads, this is a major change, should redesign
language syntax, standard library, ZendVM.
This proposal must be discussed extensively and in-depth, should not
make a hasty decision.There are 7 parts to consider with my experience:
EventLoop API
Fiber/Coroutine/GreenThread
IO-Scheduler (Socket/FileSystem/ChildProcess/Signal/Timer/Stdout/Stdin)
CPU-Scheduler
Compatible with existing extesions
(php_streams/ext-sockets/ext-redis/ext-mysqli/ext-pdo-mysql/ext-curl ...)
and builtin-functions (sleep/gethostbyname/proc_open/file_get_contents)Service container, How to support php-fpm and provide a coroutine
version of http serverCoroutine communication, How to pass messages between two coroutines
It’s nice to see php has such topic. This may be the key technology in the
next generation of PHP.Thanks
Tianfeng.Han
So from what I understand, and correct me if I'm wrong, you're against
Fibers because it doesn't include all the other systems needed to make them
immediately usable with the traditional APIs?
This sound a bit to me to wanting to run a marathon before even having
learned how to walk.
You said it yourself Swoole took years to implement all those changes,
and which is pure feature creep for what the RFC process is designed for
IMHO.
The point of this RFC, from what I see, is to bring the foundational system
into core upon which one can build upon, be that in userland or in the
extension land (when an internal API is added).
Upon which all of those different tools can be added to the language
independently, via separate RFCs, by being a PHP library or a PHP extension.
So can you please explain to us, why not adding one of the seven parts
you've stated are necessary and doing gradual implementations of the other
tools should not be done?
Because if the idea is to add all of these tools at once in a massive RFC,
I feel this is going the same way as trying to add unicode support to PHP,
and we know where that ended.
Best regards,
George P. Banyard
2021年3月12日 上午5:50,Dan Ackroyd Danack@basereality.com 写道:
Hi Twosee, Tianfeng.Han
I was drafting a longer reply to you both, but I realised I might be
missing some information.Please could you disclose the commercial interests of the Swoole
maintainers, and the ties to the for profit companies that provide
services implementing Swoole?Having people vote on RFCs who have ties to companies that provide
services via commercial entities isn't unprecedented. For example
zend.com has had employees who are involved in voting on RFCs, but to
a large extent that was done openly, with all of them using zend.com
email addresses.twosee wrote:
Of course, the Swoole community still expects to merge it into php-src at an appropriate time.
What's your idea of an appropriate time and how do you plan to start
this conversation?If something hasn't been merged back after 8 years, it sounds
reasonably unlikely that it's ever going to be merged back.cheers
Dan
Ack--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi all,
The following are some of my personal views, any comment is welcome:
What's your idea of an appropriate time and how do you plan to start
this conversation?
Maybe, I misunderstood the rules of the PHP RFC voting. In my opinion, the PHP RFC drafters need to have considerable experience in PHP kernel development (I mean that I don’t think I have met such requirements yet). And the RFC content needs to be fully verified by unit tests and actual projects, and the API or code implementation should be very stable. Once determined, no major changes will be made in principle.
But now, there is another way shown in front of me. We can draft an RFC first, then complete it based on community feedback, mark it as experimental, and continue to iterate in the PHP core. What I have to admit here is that drafting Swow's RFC will be more difficult than Fiber, because the content of the former is many times than that of the latter. However, to my surprise, it seems that there are not as many people who care about the details of the internal implementation as I thought. Most people care more about the content in the user space, and things under the user space are very easy to modify.
In addition, due to language and network barriers, people active in the Swoole community rarely participate in discussions in the PHP core community. In fact, I started subscribing to the PHP internal mailing list in July 2020 and occasionally show my opinion there. I often worry that incorrect translations will cause my intentions to be misinterpreted, and other members of the Swoole community never participated in discussions. We hardly use non-local social media. I just registered an account on Reddit, a great community exchange website yesterday, and I haven't had time to read all the discussions on that.
For all of the above reasons, it is extremely difficult for me to draft the RFC, and I have always hoped that I can make more contributions to other aspects of the PHP kernel, and then try to propose a huge coroutine draft as a goal of PHP9. And I have not taken the first step so far, I am very sorry about that.
Anyway, I will share content about Swow soon and try to draft a proposal.
If something hasn't been merged back after 8 years, it sounds
reasonably unlikely that it's ever going to be merged back.
Swoole does have a long history, what I have to point out is that the early Swoole did not really participate in the international open-source community. And Swoole switched from the pure asynchronous mode to the coroutine mode in 2018. At that time, we found that the PHP kernel has a good wrapping for various IO operations. We only need to implement the coroutine version of php_stream_wrapper to turn all relevant synchronous clients into coroutine clients or make synchronization blocking file operations into coroutine way. In this case, we can use a very small amount of work to achieve the reuse of most of the original libraries of the PHP native ecosystem. But Swoole gradually becomes a C++ project with some technical plan, so that it makes Swoole hard to be merged into php-src.
I started programming in 2017 and contributed to the Swoole project in 2018. In 2019, I learned and mastered almost all the technical content of Swoole. In 2020, I obtained a php.net account. At the same time, I also created a new systematic pure C coroutine project called Swow (for sure, it can be called any other name, but the name Swow is only respect for Swoole because Swow leans in the implementation principle of Swoole and its technical experience) , and I plan to propose a systematic draft of coroutine this year. I have paid my best to accelerate this process. For the PHP community, everyone really needs a real asynchronous/coroutine solution. Therefore, I totally understand the criticism of the slow progress. But, sorry from the bottom of my heart. I can't do it faster.
Are you saying that by adding this Fiber code to core it will prevent
Swoole from functioning? If so, that is concerning. Or are you
simply saying that Swoole doesn't like this implementation and will not use
it with their own code?
First of all, please let me pay tribute to your work. I fully understand that the implementation of Fiber could be indeed compatible with Swoole/Swow because theoretically nothing is incompatible. However, undoubtedly, for some reasons I mentioned or not mentioned, this requires a considerable amount of work. Of course, I am not completely denying the feature of Fiber, I just cannot agree with the merger of ext-fiber now. We always regard merging the coroutine system into php-src as a systematic plan. Even if the implementation of ext-fiber is merged, I am still willing to overcome difficulties to make more changes to promote the merger of Swow into php-src, it's my pleasure.
One thing to consider when comparing the Fiber implementation is that the
vast majority of PHP applications are still run behind a web server in
short-lived requests. Unlike Swoole, Swow, and Parallel, it isn't limited
to ZTS or CLI. It might not be the ideal solution, but IMO it is a step in
the right direction for PHP to allow for better async support.
There is a misunderstanding here. Swow has made improvements in this area. It supports NTS, ZTS, supports running under all SAPIs (including FPM), and also supports running under all operating systems.
Now, Swow's working principle is a bit like Opcache. Opcache will optimize and replace the CPU instructions, which executed by the code, and Swow will replace the blocking system calls with the corresponding coroutine operation. They hardly change the behavior of the code. Opcache makes The program runs faster, and Swow can make the program's IO concurrency better.
Therefore, all PHP programs will benefit from it. We can directly use the synchronous-blocking guzzle. Any network IO will only block one coroutine instead of the entire process. You just need to open more coroutines to get better concurrency performance. For amphp and reactphp, after that, stream_select()
and curl_multi_select()
will become the coroutine version, and even they will no longer block the entire program.
Generally, the solution provided by Swow is completely a superset of Fiber.
By the way, Tianfeng’s translation may have caused some misunderstandings. I think what he wants to express is that Fiber is not a feature that can directly benefit all PHP projects. Of course, I know that the RFC has mentioned that Fiber is mainly provided for the author of the framework and library uses. Sorry for this that caused misunderstanding.
Regards,
Twosee
Now, Swow's working principle is a bit like Opcache. Opcache will optimize and replace the CPU instructions, which executed by the code, and Swow will replace the blocking system calls with the corresponding coroutine operation. They hardly change the behavior of the code. Opcache makes The program runs faster, and Swow can make the program's IO concurrency better.
Therefore, all PHP programs will benefit from it. We can directly use the synchronous-blocking guzzle. Any network IO will only block one coroutine instead of the entire process. You just need to open more coroutines to get better concurrency performance. For amphp and reactphp, after that,
stream_select()
andcurl_multi_select()
will become the coroutine version, and even they will no longer block the entire program.Generally, the solution provided by Swow is completely a superset of Fiber.
Hi Twosee,
I wanted to address the point above from your email. I do not think auto-magically altering the behavior of existing functions to use async I/O is a good idea. Existing code that relies on a constant state during an I/O operation that previously was blocking may no longer work as expected. Changing behavior is a major BC break. It would be better to introduce new async versions of functions, e.g., asio_fwrite(), instead of altering the existing fwrite()
function. This way libraries which have interfaces requiring blocking I/O, such as libraries implementing PSR-7/15, can create versions that are designed with async I/O in mind, while keeping existing implementations working as expected.
Changing the behavior of existing functions reminds me of the mbstring.func_overload
feature that is now deprecated because of the compatibility problems it caused.
I took a look at Swow this morning. Again, I would compare Swow to Swoole – it is another large, opinionated framework for asynchronous PHP apps. Swow is not a lightweight, standalone feature that can be merged into PHP at one time. The Fiber API is small in scope and does not alter existing behaviors.
Looking at the fiber implementation in Swow, I see it uses the same boost library and the same asymmetric coroutine model as ext-fiber. It seems Swow could use an internal API provided by PHP for fibers, allowing it to drop the boost dependency.
This leads me to believe my proposal would be mutually beneficial to both your extension and the wider PHP community that could use fibers outside of your framework or Swoole.
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 PiotrowskiTo unsubscribe, visit: https://www.php.net/unsub.php
Hi everyone!
I’m concerned my email above may have had the opposite effect from which I had hoped.
I think the Fiber implementation is sound and the API, mirroring that of Ruby, is proven and unlikely to require change.
There are certain edge case behaviors that I’m concerned may need to changed, such as the error reporting level that is active when a fiber is switched. If the @ operator is active, should it remain active after a fiber switch? Right now, it does not, the @ operator is on a per-fiber basis, restoring error reporting when switching fibers. Perhaps though this was the wrong decision. What I was hoping to accomplish with marking the feature as experimental was to get feedback on such behaviors and make sure we make the right choices.
Recent changes to the JIT also make fibers as an extension incompatible due to defining a user opcode handler. This is unfortunate, as cli apps including amphp and ReactPHP greatly benefited from the JIT: https://www.php.net/releases/8.0/en.php (see Relative JIT contribution to PHP 8 performance). Integrating fibers in core will allow the opcode handler to be predefined.
Hopefully that provides some clarity to our intensions. Cheers!
Aaron Piotrowski
Hi internals,
Well, technically this is addressed more to people who read internals.
Please don't contact people off list putting pressure on them to vote
in a particular way.
It really is not appreciated, no matter how well intentioned the
sender thinks it is.
I maintain some notes on RFC etiquette here:
https://github.com/Danack/RfcCodex/blob/master/rfc_etiquette.md#dont-pressure-people-by-private-communication-to-vote
(which not even is going to fully agree with), but getting unsolicited
pressure to vote in a particular way makes people uncomfortable, and
less likely to take part in the project in the future.
cheers
Dan
Ack
= Don't pressure people by private communication to vote
Even with the best intentions, unsolicited off-list communications
putting pressure on people to vote a particular way are rude. At best
they don't have any effect, but most of the time they make the
recipient uncomfortable.
If you want to influence how people are going to vote, these things
are appropriate:
- Sending an email to internals saying that you would like to see this pass.
- Posting on Reddit /r/php or other platform where discussions take
place, and then posting a link to internals, saying "these are my
thoughts". - Asking in a public communication channel asking someone in a neutral
way 'are you going to vote?'.
Private communications trying to change people's minds are a burden
that make people receiving them feel bad, even if they are intentioned
to help the project.
Hi internals,
Well, technically this is addressed more to people who read internals.
Please don't contact people off list putting pressure on them to vote
in a particular way.It really is not appreciated, no matter how well intentioned the
sender thinks it is.I maintain some notes on RFC etiquette here:
https://github.com/Danack/RfcCodex/blob/master/rfc_etiquette.md#dont-pressure-people-by-private-communication-to-vote
(which not even is going to fully agree with), but getting unsolicited
pressure to vote in a particular way makes people uncomfortable, and
less likely to take part in the project in the future.cheers
Dan
Ack
Hi everyone,
While I appreciate the support from the individual that sent the email, I do not condone sending emails to people privately off list asking them to vote in a particular way.
For clarification to those that may have not received the email in question, I did not send the email nor did I request that it be sent.
Thanks,
Aaron Piotrowski
Den ons. 10. mar. 2021 kl. 20.22 skrev Dan Ackroyd Danack@basereality.com:
Hi internals,
Well, technically this is addressed more to people who read internals.
Please don't contact people off list putting pressure on them to vote
in a particular way.It really is not appreciated, no matter how well intentioned the
sender thinks it is.
For the sake of integrity, I believe the vote should be halted and
restarted at a later date to prevent the influence of referenced email
from having a favored vote. This has no relation to my personal vote
on the matter of the RFC however.
--
regards,
Kalle Sommer Nielsen
kalle@php.net
Den ons. 10. mar. 2021 kl. 20.22 skrev Dan Ackroyd <Danack@basereality.com
:
Hi internals,
Well, technically this is addressed more to people who read internals.
Please don't contact people off list putting pressure on them to vote
in a particular way.It really is not appreciated, no matter how well intentioned the
sender thinks it is.For the sake of integrity, I believe the vote should be halted and
restarted at a later date to prevent the influence of referenced email
from having a favored vote. This has no relation to my personal vote
on the matter of the RFC however.
If the email was sent by the RFC authors itself I would agree, but it was
not.
Stopping the vote because of this would provide precedent to bombard any
RFC vote by just emailing all voters a nasty email.
--
regards,Kalle Sommer Nielsen
kalle@php.net--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi Aaron!
Thank you, and everyone involved, for your effort.
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.
I voted /no/, because of the dependency on Boost.
If my assumptions are wrong, I may reconsider my vote.
--
Regards,
Mike
Hi Aaron!
Thank you, and everyone involved, for your effort.
Greetings everyone!
The vote has started on the fiber RFC:
https://wiki.php.net/rfc/fibers https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
I voted /no/, because of the dependency on Boost.
If my assumptions are wrong, I may reconsider my vote.
IIRC, that dependency is the inclusion of a single header file, there is no linkage against boost. The header file can be bundled.
cheers,
Derick
Thank you, and everyone involved, for your effort.
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.
I voted /no/, because of the dependency on Boost.
If my assumptions are wrong, I may reconsider my vote.
Only asm files are used[1], and these can be bundled, so there is no
dependency on boost or C++ in general.
[1] https://github.com/amphp/ext-fiber/tree/master/boost
--
Christoph M. Becker
Thank you, and everyone involved, for your effort.
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.
I voted /no/, because of the dependency on Boost.
If my assumptions are wrong, I may reconsider my vote.Only asm files are used[1], and these can be bundled, so there is no
dependency on boost or C++ in general.[1] https://github.com/amphp/ext-fiber/tree/master/boost
--
Christoph M. Becker
Hi Mike, Christoph, and Derick,
To add a bit more information:
These asm files are part of the low-level boost.context lib, found here: https://github.com/boostorg/context
This library has infrequent releases. Some of the files for old architectures have not changed in several years. Keeping these files up-to-date will not be a burden (and I plan to assume this responsibility).
The Boost license is extremely permissive and approved by the OSI, so there is no problem bundling with PHP.
Hopefully that provides some clarification and you’ll reconsider your vote Mike.
Cheers!
Aaron Piotrowski
Thank you, and everyone involved, for your effort.
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.
I voted /no/, because of the dependency on Boost.
If my assumptions are wrong, I may reconsider my vote.Only asm files are used[1], and these can be bundled, so there is no
dependency on boost or C++ in general.[1] https://github.com/amphp/ext-fiber/tree/master/boost
--
Christoph M. BeckerHi Mike, Christoph, and Derick,
To add a bit more information:
These asm files are part of the low-level boost.context lib, found here: https://github.com/boostorg/context
This library has infrequent releases. Some of the files for old architectures have not changed in several years. Keeping these files up-to-date will not be a burden (and I plan to assume this responsibility).
The Boost license is extremely permissive and approved by the OSI, so there is no problem bundling with PHP.
Hopefully that provides some clarification and you’ll reconsider your vote Mike.
Cheers!
Aaron Piotrowski--
To unsubscribe, visit: https://www.php.net/unsub.php
Apologies, this is a long one!
This RFC strikes me as being very dangerous. Implicitly allowing code
which is synchronous by design to be executed asynchronously seems
sure to lead to very subtle, unpredictable, confusing and dangerous
bugs.
The issue is that executing code asynchronously introduces race
conditions and, in code which is synchronous by design, those race
conditions will lead to bugs which will never occur during QA or
development and will be incredibly hard to identify once they do occur
in production.
These are the kind of bugs where user sessions get mixed up, the wrong
package is installed by a package manager, or an ecommerce website
captures the wrong amount of money from a customer's credit card. And
developers will have no realistic way of tracking down why these
things are happening in real world, multi developer, multi vendor PHP
applications.
For example, the PHP ecosystem is full of code like this:
private function capturePayment()
{
$paymentRequest = preparePaymentRequest($this->currentOrder);
$this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}
In the above code snippet, the developer has relied on the fact that
the mutable value $this->currentOrder will be the same before and
after the call to $this->capturePayment(), because capturePayment() is
synchronous. In all likelihood, the authoring PHP developer is not
even familiar with asynchronicity, and the assumption that
capturePayment() is synchronous is therefore not even a conscious one.
Note that, if capturePayment is executed asynchronously, eventually we
will see payments attributed to the wrong orders.
Note that, if fibers land, there is no know whether the code above is
correct by looking at it in isolation. You can only know that by
knowing the environment in which the code is executed, as well as
understanding all of the internals of capturePayment(), and its
dependencies, many of which will probably managed by other developers
and will involve a bunch of injected services, many of which will do
IO and therefore are candidates for using fibers, directly or
indirectly, such as logging, HTTP, and database.
The worst characteristics to me are the following:
- These race conditions will cause problems so rarely that developers
will not even realise that their programs contain dangerous bugs. Code
which is not safe to use with fibers will appear to be functional
because the happy path will work fine, and so developers will assume
it's okay. - Changes very, very far away from your code can cause your code to
become unexpectedly asynchronous. Imagine you are using the DynamoDB
monolog logger in your application, and that library indirectly uses
Guzzle, which gets fiber support. Any place you are logging anything
now becomes asynchronous, as well as any code which invokes that code.
If you are using some kind of event dispatch pattern then pretty much
everything in your program becomes asynchronous. - As a library author, there is no way of knowing how your code is
going to be used, and what injected dependencies might use fibers
internally.
The counter arguments:
- "The above code snippet is suboptimal, it shouldn't assume that
mutable state remains unchanged following some IO, and the order
should be passed in as an arg." -- Whether or not this is true is
irrelevant -- developers have relied on the invariants of the PHP
language when writing their code, such as synchronous code being
synchronous, and this is how lots of code is written in the wild. If
this feature lands, that won't change -- very few userland developers
will understand this feature, including library authors. - "Fibers should only be enabled in async first programs." and "We
could flag that certain libraries are fiber compatible or
incompatible." If code appears to work in a fiber environment, people
will just use it in a fiber environment, without understanding all of
the security issues and horrible bugs they're introducing. This
problem should rather be solved at the language level by making async
explicit.
Consider the following:
private async function capturePayment()
{
$paymentRequest = preparePaymentRequest($this->currentOrder);
await $this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}
Looking at the above code, I can see the race condition. It becomes
explicit. So I change the code and communicate explicitly via the type
system that this function is asynchronous and that my code expects
PaymentGateway::capturePayment() to be asynchronous.
private async function capturePayment()
{
$order = $this->currentOrder;
$paymentRequest = preparePaymentRequest($order);
await $this->paymentGateway->capturePayment($paymentRequest);
$order->setTransactionId($paymentRequest->getTransactionId());
}
Regarding PHP's type system not supporting generics, and the
associated advantages of this RFC over promises; I agree that this is
a problem with promises. But the lack of generics in PHP already means
we have no language-level type safety on data structures, which is
certainly worse than not having type safety on promises. Psalm et al
have provided reasonable solutions to this issue.
Sorry for the criticism of the idea -- I've used React and Amp in
production on a product which has been in prod for many years -- and
I'd be happy to see first class asynchronous support within the
language, but I think this RFC would make the language worse, not
better. Technically, I'm sure this is great, and I do appreciate that
a lot of work has probably been put into this.
Thanks
Hello everyone,
I'm just adding a few cents into this discussion.
I've voted "yes" because we don't have any other async stuff RFCs available
nor in the preparation. PHP needs such functionalities very badly and very
quickly to sort of speak. Adding a brand new extension in the core is maybe
a strange practice because it usually should go into PECL first and after
being adopted by the ecosystem it could be then moved to php-src after a
vote. However, practical reasons show that PECL extensions are not first
class citizens. In most cases adopting extensions could take even longer.
With somehow similar logic, I've also supported FFI extension and even Jit
RFCs already in 7.4.
Regarding Swoole, Swoole is a great production-ready framework that
provides such functionality also already today. It is definitely worth
checking out from a user perspective and can live along the ext-fiber just
fine, I believe. If Swoole won't be integrated in core (it is a separate
standalone project), then hopefully, PHP core could learn and be inspired
by Swoole as it's already implemented in production with unbeatable
performance.
Thank you to the RFC authors and everyone involved in making this happen.
Hey Josh,
Apologies, this is a long one!
This RFC strikes me as being very dangerous. Implicitly allowing code
which is synchronous by design to be executed asynchronously seems
sure to lead to very subtle, unpredictable, confusing and dangerous
bugs.
Thank you for sharing your thoughts, I'll respond inline for better
context, but shortened some paragraphs for better readability.
[...]
For example, the PHP ecosystem is full of code like this:
private function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder); $this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}In the above code snippet, the developer has relied on the fact that
the mutable value $this->currentOrder will be the same before and
after the call to $this->capturePayment() [...]
This is a very valid concern to have. However, this code won't simply break
if executed asynchronously.
It only breaks if the same method (or other methods making use of the same
state) is executed concurrently on that object.
[...]
- These race conditions will cause problems so rarely that developers
will not even realise that their programs contain dangerous bugs. [...]- Changes very, very far away from your code can cause your code to
become unexpectedly asynchronous. [...]- As a library author, there is no way of knowing how your code is
going to be used, and what injected dependencies might use fibers
internally.The counter arguments:
- "The above code snippet is suboptimal, it shouldn't assume that
mutable state remains unchanged following some IO, and the order
should be passed in as an arg." [...]- "Fibers should only be enabled in async first programs." and "We
could flag that certain libraries are fiber compatible or
incompatible." [...]Consider the following:
private async function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder); await $this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}Looking at the above code, I can see the race condition. It becomes
explicit. So I change the code and communicate explicitly via the type
system that this function is asynchronous and that my code expects
PaymentGateway::capturePayment() to be asynchronous.
If you can see the race condition here, you can probably also see the race
condition in the original snippet above.
The overall issue you're describing is thread safety and mutable state. It
exists with fibers, but a very similar issue exists with explicit async /
await.
Just because something supports asynchronous I/O, doesn't mean it also
supports concurrent operations on its state.
It might be a good idea to introduce some guarding concept in a follow-up
RFC, so objects can easily protect against being used concurrently e.g.
private synchronized function capturePayment()
{
$paymentRequest = preparePaymentRequest($this->currentOrder);
$this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}
"synchonized" isn't the right keyword here, but I can't think of a better
name right now.
Regarding PHP's type system not supporting generics, and the
associated advantages of this RFC over promises; I agree that this is
a problem with promises. But the lack of generics in PHP already means
we have no language-level type safety on data structures, which is
certainly worse than not having type safety on promises. Psalm et al
have provided reasonable solutions to this issue.
Being able to use the type system is a concern the RFC solves, but that's
rather just nice-to-have. The relevant problem is the call stack pollution
or "What color is your function" problem. It simply doesn't make sense for
applications and libraries to offer an async and non-async interface for
everything. Due to the "What color is your function" problem, there can't
be a gradual migration to non-blocking I/O, which will mostly result in
non-blocking I/O simply not being supported by the majority of libraries,
making it basically non-viable in PHP.
Best,
Niklas
Hey Josh,
Apologies, this is a long one!
This RFC strikes me as being very dangerous. Implicitly allowing code
which is synchronous by design to be executed asynchronously seems
sure to lead to very subtle, unpredictable, confusing and dangerous
bugs.Thank you for sharing your thoughts, I'll respond inline for better context, but shortened some paragraphs for better readability.
Many thanks for the detailed reply. I've replied inline.
[...]
For example, the PHP ecosystem is full of code like this:
private function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder); $this->paymentGateway->capturePayment($paymentRequest); $this->currentOrder->setTransactionId($paymentRequest->getTransactionId()); }
In the above code snippet, the developer has relied on the fact that
the mutable value $this->currentOrder will be the same before and
after the call to $this->capturePayment() [...]This is a very valid concern to have. However, this code won't simply break if executed asynchronously.
It only breaks if the same method (or other methods making use of the same state) is executed concurrently on that object.
I understand this, but of course this will be common in programs where
fibers are used, and the nature of this proposal means that fibers
will potentially be highly insidious and quite unpredictable in their
reach.
[...]
- These race conditions will cause problems so rarely that developers
will not even realise that their programs contain dangerous bugs. [...]- Changes very, very far away from your code can cause your code to
become unexpectedly asynchronous. [...]- As a library author, there is no way of knowing how your code is
going to be used, and what injected dependencies might use fibers
internally.The counter arguments:
- "The above code snippet is suboptimal, it shouldn't assume that
mutable state remains unchanged following some IO, and the order
should be passed in as an arg." [...]- "Fibers should only be enabled in async first programs." and "We
could flag that certain libraries are fiber compatible or
incompatible." [...]Consider the following:
private async function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder); await $this->paymentGateway->capturePayment($paymentRequest); $this->currentOrder->setTransactionId($paymentRequest->getTransactionId()); }
Looking at the above code, I can see the race condition. It becomes
explicit. So I change the code and communicate explicitly via the type
system that this function is asynchronous and that my code expects
PaymentGateway::capturePayment() to be asynchronous.If you can see the race condition here, you can probably also see the race condition in the original snippet above.
The difference is that in the second case, the developer has
explicitly opted into the underlying call being async. I.e. they
expect it, and can design with it in mind.
The overall issue you're describing is thread safety and mutable state. It exists with fibers, but a very similar issue exists with explicit async / await.
Just because something supports asynchronous I/O, doesn't mean it also supports concurrent operations on its state.It might be a good idea to introduce some guarding concept in a follow-up RFC, so objects can easily protect against being used concurrently e.g.
private synchronized function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder); $this->paymentGateway->capturePayment($paymentRequest); $this->currentOrder->setTransactionId($paymentRequest->getTransactionId()); }
"synchonized" isn't the right keyword here, but I can't think of a better name right now.
Regarding PHP's type system not supporting generics, and the
associated advantages of this RFC over promises; I agree that this is
a problem with promises. But the lack of generics in PHP already means
we have no language-level type safety on data structures, which is
certainly worse than not having type safety on promises. Psalm et al
have provided reasonable solutions to this issue.Being able to use the type system is a concern the RFC solves, but that's rather just nice-to-have. The relevant problem is the call stack pollution or "What color is your function" problem. It simply doesn't make sense for applications and libraries to offer an async and non-async interface for everything. Due to the "What color is your function" problem, there can't be a gradual migration to non-blocking I/O, which will mostly result in non-blocking I/O simply not being supported by the majority of libraries, making it basically non-viable in PHP.
Perhaps we could rather make fibers opt in at the callsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem. For example
private function capturePayment(): void
{
$paymentRequest = preparePaymentRequest($this->currentOrder);
// allow, but don't require, the underlying call to use
fibers. Callers higher up the stack would also have to opt in
async $this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}
With this approach, APIs we'd avoid the "what colour is your function"
problem without sacrificing the safety that we really need in e.g.
ecommerce.
Best,
Niklas
Thanks again for engaging.
Hey Josh,
This is a very valid concern to have. However, this code won't simply
break if executed asynchronously.
It only breaks if the same method (or other methods making use of the
same state) is executed concurrently on that object.I understand this, but of course this will be common in programs where
fibers are used, and the nature of this proposal means that fibers
will potentially be highly insidious and quite unpredictable in their
reach.
Concurrent operations on stateful, mutable objects are certainly a risk and
concurrency shouldn't be introduced without thinking about the
consequences. Care must be taken if objects are used across different
fibers concurrently, unless you use global state, then you'll have a harder
time adding concurrency to your application.
If you can see the race condition here, you can probably also see the
race condition in the original snippet above.The difference is that in the second case, the developer has
explicitly opted into the underlying call being async. I.e. they
expect it, and can design with it in mind.
While the developer opted into async / non-blocking I/O, they still might
not have thought about concurrent operations on that same object.
Being able to use the type system is a concern the RFC solves, but that's
rather just nice-to-have. The relevant problem is the call stack pollution
or "What color is your function" problem. It simply doesn't make sense for
applications and libraries to offer an async and non-async interface for
everything. Due to the "What color is your function" problem, there can't
be a gradual migration to non-blocking I/O, which will mostly result in
non-blocking I/O simply not being supported by the majority of libraries,
making it basically non-viable in PHP.Perhaps we could rather make fibers opt in at the callsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem. For exampleprivate function capturePayment(): void { $paymentRequest = preparePaymentRequest($this->currentOrder); // allow, but don't require, the underlying call to use
fibers. Callers higher up the stack would also have to opt in
async $this->paymentGateway->capturePayment($paymentRequest);$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}With this approach, APIs we'd avoid the "what colour is your function"
problem without sacrificing the safety that we really need in e.g.
ecommerce.
This doesn't really avoid the "what color is your function" problem, as
you'd have to mark all function calls with "async" then, eventually
resulting in every PHP function call having to be prefixed with "async".
Rather than marking methods with "synchronized" as mentioned before, it
might be more feasible to mark methods with a keyword if they allow
concurrent operations. I'll have to research which options are viable.
Best,
Niklas
Hi Niklas,
Hey Josh,
This is a very valid concern to have. However, this code won't simply break if executed asynchronously.
It only breaks if the same method (or other methods making use of the same state) is executed concurrently on that object.I understand this, but of course this will be common in programs where
fibers are used, and the nature of this proposal means that fibers
will potentially be highly insidious and quite unpredictable in their
reach.Concurrent operations on stateful, mutable objects are certainly a risk and concurrency shouldn't be introduced without thinking about the consequences. Care must be taken if objects are used across different fibers concurrently, unless you use global state, then you'll have a harder time adding concurrency to your application.
I think this is wishful thinking. Real world software uses code from
lots of developers and vendors. We can never realistically know the
internals of our whole codebase or read through every line of code in
order to evaluate whether we think each library we are using has been
designed with fiber support in mind. A solution which relies on this
is wishful thinking.
If you can see the race condition here, you can probably also see the race condition in the original snippet above.
The difference is that in the second case, the developer has
explicitly opted into the underlying call being async. I.e. they
expect it, and can design with it in mind.While the developer opted into async / non-blocking I/O, they still might not have thought about concurrent operations on that same object.
But at least you know that the developer intends for the code to be
run with fibers. This is especially important for third party code.
Being able to use the type system is a concern the RFC solves, but that's rather just nice-to-have. The relevant problem is the call stack pollution or "What color is your function" problem. It simply doesn't make sense for applications and libraries to offer an async and non-async interface for everything. Due to the "What color is your function" problem, there can't be a gradual migration to non-blocking I/O, which will mostly result in non-blocking I/O simply not being supported by the majority of libraries, making it basically non-viable in PHP.
Perhaps we could rather make fibers opt in at the callsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem. For exampleprivate function capturePayment(): void { $paymentRequest = preparePaymentRequest($this->currentOrder); // allow, but don't require, the underlying call to use
fibers. Callers higher up the stack would also have to opt in
async $this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}With this approach, APIs we'd avoid the "what colour is your function"
problem without sacrificing the safety that we really need in e.g.
ecommerce.This doesn't really avoid the "what color is your function" problem, as you'd have to mark all function calls with "async" then, eventually resulting in every PHP function call having to be prefixed with "async".
I certainly don't think we should expect to be in a position where all
functions are async. Business logic is (should generally be) in pure,
side effect free functions which, by definition, are not doing any IO.
The point is to avoid accidentally making that code async.
To clarify, my suggestion is that a keyword at the callsite would
allow the callsite to opt in to fibers in the called function if that
function supports fibers, and if we are currently within a fiber
context, otherwise it would behave synchronously.
Rather than marking methods with "synchronized" as mentioned before, it might be more feasible to mark methods with a keyword if they allow concurrent operations. I'll have to research which options are viable.
Best,
Niklas
I do appreciate your time, and I'm sorry for not asking these
questions during the discussion period. I'll leave it here unless
others feel the discussion is worth continuing.
Thanks
Perhaps we could rather make fibers opt in at the callsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem. For exampleprivate function capturePayment(): void { $paymentRequest = preparePaymentRequest($this->currentOrder); // allow, but don't require, the underlying call to use
fibers. Callers higher up the stack would also have to opt in
async $this->paymentGateway->capturePayment($paymentRequest);$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}With this approach, APIs we'd avoid the "what colour is your function"
problem without sacrificing the safety that we really need in e.g.
ecommerce.
"Callers higher up the stack would also have to opt in" is precisely and specifically the design flaw that fibers avoid. What you're suggesting is that a given IO call would become magically non-blocking iff its entire parent call stack was called with async
keywords, which could be 50 stack frames easily. Aside from the implementation challenge, and the fact that it would require two different code paths even in the PHP code around that IO, even if it could be implemented it would mean that basically no IO code would ever run async, ever, because there is one function call somewhere in the stack that didn't include async
in some library that everyone uses but hasn't been updated to prefix every single function call with async
.
That is literally the "What color is your function" problem.
I should also note that if you are following good practices to begin with, your code base is 90% pure, immutable functions/methods and so entirely safe from cooperative multitasking race conditions. If that's not the case, you have a buggy codebase already even without fibers. Fibers would just make it more obvious.
--Larry Garfield
Hi Larry,
Thanks for the feedback. Replies inline.
Perhaps we could rather make fibers opt in at the callsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem. For exampleprivate function capturePayment(): void { $paymentRequest = preparePaymentRequest($this->currentOrder); // allow, but don't require, the underlying call to use
fibers. Callers higher up the stack would also have to opt in
async $this->paymentGateway->capturePayment($paymentRequest);$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}With this approach, APIs we'd avoid the "what colour is your function"
problem without sacrificing the safety that we really need in e.g.
ecommerce."Callers higher up the stack would also have to opt in" is precisely and specifically the design flaw that fibers avoid.
What you are calling a design flaw, is by far the most common approach
to async in other languages.
What you're suggesting is that a given IO call would become magically non-blocking iff its entire parent call stack was called with
async
keywords, which could be 50 stack frames easily. Aside from the implementation challenge, and the fact that it would require two different code paths even in the PHP code around that IO ...
This is already the case with the fiber RFC as it stands. If you are
not within fiber context, then calls to fiber-enabled are sync. If you
are within fiber context, they're async.
... event if it could be implemented it would mean that basically no IO code would ever run async, ever, because there is one function call somewhere in the stack that didn't include
async
in some library that everyone uses but hasn't been updated to prefix every single function call withasync
.
This is very close to how goroutines work in Golang.
That is literally the "What color is your function" problem.
Some of the "problems" are still present, but I am still suggesting
that there be only one implementation of each function, rather than
two, and that implementation can be called from either a synchronous
or asynchronous context.
I should also note that if you are following good practices to begin with, your code base is 90% pure, immutable functions/methods and so entirely safe from cooperative multitasking race conditions.
Right, but that code should generally be synchronous, because if a
function is async then it's doing IO and isn't a pure function. But
note that as this RFC stands there's no way to know that without
actually reading all the code. Perhaps you are rather talking about
side effects, it's unclear.
If that's not the case, you have a buggy codebase already even without fibers. Fibers would just make it more obvious.
Fibers will not make those issues obvious at all. The issues I'm
describing will only crop up spontaneously and under load.
--Larry Garfield
--
To unsubscribe, visit: https://www.php.net/unsub.php
Cheers
Fibers will not make those issues obvious at all. The issues I'm
describing will only crop up spontaneously and under load.
Hi Josh,
Is this really that big of a concern though? The issue will only be a
problem if it's run inside an event loop/scheduler that the concerned
library is compatible with. In which case the developer should be well
aware of what is involved.
Otherwise, if the library uses fibers internally it will have to resolve
them itself before continuing, no? If capturePayment()
starts a fiber
then execution will not get to setTransactionId()
, until it completed or
is handed of to a scheduler (again, which the developer would be aware of.
So I don't think developers will face this race condition, unless they are
using framework like amphp and reactphp. But that's already the same now,
so if it's an issue it's not a new one with this RFC.
Your average unaware developer can continue to happily use any libraries
they want without encountering any async issues. The calls from outside
the library will still be blocking, as PHP will still be single threaded.
Thanks,
Peter
Hi Peter,
Thanks for the feedback!
Fibers will not make those issues obvious at all. The issues I'm
describing will only crop up spontaneously and under load.Hi Josh,
Is this really that big of a concern though? The issue will only be a problem if it's run inside an event loop/scheduler that the concerned library is compatible with. In which case the developer should be well aware of what is involved.
Not exactly, no. As a library author, code you wrote without fibers in
mind can become async.
Imagine for a moment that you create a library, awesome-library-x,
which uses a PSR logger internally. You will most certainly allow that
logger to be injected into your library. Now imagine that some other
developer uses awesome-library-x in their application, and injects it
with a monolog logger that logs to some AWS service via the AWS SDK.
In turn, that logger indirectly uses Guzzle, which adds fiber support.
As a result, any functions in awesome-library-x which log something
become asynchronous. Two changes made by two developers unrelated to
awesome-library-x cause its code to be executed asynchronously.
Otherwise, if the library uses fibers internally it will have to resolve them itself before continuing, no? If
capturePayment()
starts a fiber then execution will not get tosetTransactionId()
, until it completed or is handed of to a scheduler (again, which the developer would be aware of.So I don't think developers will face this race condition, unless they are using framework like amphp and reactphp. But that's already the same now, so if it's an issue it's not a new one with this RFC.
It is a new issue. Today, interruptible functions must include a
yield
statement, so they are explicitly interruptible.
Your average unaware developer can continue to happily use any libraries they want without encountering any async issues. The calls from outside the library will still be blocking, as PHP will still be single threaded.
Thanks,
Peter
I feel like we're going round in circles a bit, and I don't want to
drown everyone in emails, especially as we're out of the discussion
period for this RFC. I will try to clarify my point and attempt to
summarise the counterpoint to reduce noise.
My opinion is that, in a world of multi-vendor applications and
dependency injection, async can't safely be an implicit feature, it
needs to be explicit. It should be noted that virtually all general
purpose programming languages seem to take this view, including, for
example, hacklang.
The counter argument is: if you want to use fibers, you have to be
sure that your entire codebase, including all of the code you import
from other vendors, is written with fibers in mind (or is compatible
by good fortune). But this will not be made explicit in the code. I
think this is wishful thinking, and highly impractical.
And finally, to clarify one other thing, the bugs I'm talking about
are race conditions. You don't identify race conditions by executing
code, you find race conditions by reading code. So all of the code has
to be read in order to find them all, there is no shortcut. Most
people won't actually do this however.
Cheers
Imagine for a moment that you create a library, awesome-library-x,
which uses a PSR logger internally. You will most certainly allow that
logger to be injected into your library. Now imagine that some other
developer uses awesome-library-x in their application, and injects it
with a monolog logger that logs to some AWS service via the AWS SDK.
In turn, that logger indirectly uses Guzzle, which adds fiber support.
As a result, any functions in awesome-library-x which log something
become asynchronous. Two changes made by two developers unrelated to
awesome-library-x cause its code to be executed asynchronously.Otherwise, if the library uses fibers internally it will have to resolve
them itself before continuing, no? IfcapturePayment()
starts a fiber
then execution will not get tosetTransactionId()
, until it completed or
is handed of to a scheduler (again, which the developer would be aware of.So I don't think developers will face this race condition, unless they
are using framework like amphp and reactphp. But that's already the same
now, so if it's an issue it's not a new one with this RFC.It is a new issue. Today, interruptible functions must include a
yield
statement, so they are explicitly interruptible.
No, they don't need to yield. You can do $guzzleClient->requestAsync()
today, so how is it different?
Thanks,
Peter
Imagine for a moment that you create a library, awesome-library-x,
which uses a PSR logger internally. You will most certainly allow that
logger to be injected into your library. Now imagine that some other
developer uses awesome-library-x in their application, and injects it
with a monolog logger that logs to some AWS service via the AWS SDK.
In turn, that logger indirectly uses Guzzle, which adds fiber support.
As a result, any functions in awesome-library-x which log something
become asynchronous. Two changes made by two developers unrelated to
awesome-library-x cause its code to be executed asynchronously.Otherwise, if the library uses fibers internally it will have to resolve them itself before continuing, no? If
capturePayment()
starts a fiber then execution will not get tosetTransactionId()
, until it completed or is handed of to a scheduler (again, which the developer would be aware of.So I don't think developers will face this race condition, unless they are using framework like amphp and reactphp. But that's already the same now, so if it's an issue it's not a new one with this RFC.
It is a new issue. Today, interruptible functions must include a
yield
statement, so they are explicitly interruptible.No, they don't need to yield. You can do
$guzzleClient->requestAsync()
today, so how is it different?Thanks,
Peter
Hi Peter,
I am referring to functions which can be interrupted or suspended.
Guzzle's requestAsync() returns a promise, it does not
interrupt/suspend the callsite. For example:
// this function is not interrupted/suspended -- it will return
synchronously
function doSomething() {
$this->guzzle->requestAsync(...)->then(... handle response here ...);
echo "This will be printed before a response is received";
}
The following is similar to how one would implement an coroutine in
PHP today when using a library which implements a coroutine mechanism,
such as amphp. Note the yield statement which interrupts/suspends the
function:
// this function will be suspended while the request is in flight
-- it will return after a response is received
function doSomething()
$response = yield $this->guzzle->requestAsync(...);
// do something with response here
echo "This will be printed AFTER the response comes back";
}
Note the difference between the two. Also note how, in both of the
above cases, the asynchronicity is explicit and the developer has
opted into it. Both of the above are different approaches to that
being proposed in this RFC (this is a design choice by the authors).
Cheers
Note the difference between the two. Also note how, in both of the
above cases, the asynchronicity is explicit and the developer has
opted into it. Both of the above are different approaches to that
being proposed in this RFC (this is a design choice by the authors).
Hi again Josh,
I think we are jumping back and forth on two different things. One is the
race condition caused by async, and the other is if the top level code
explicitly states that it is called asynchronously.
When I used the Guzzle requestAsync()
example, it was meant to show that
you can have a library do something, and then continue execution like it
had completed when in fact it had not. This could cause your
setTransactionId()
to happen before the capturePayment()
request has
completed, and in that regard it can be the same; not by how it works, but
in concept. I do know that they are different in implementation. It would
cause this without an explicit keyword showing that capturePayment()
used
an async call internally. That is what I was referring to when I said it
could also be a race condition now, without fibers.
As I was also explaining earlier, the developer must know that they are
inside an async environment, because you can't suspend the main "thread".
Fiber::suspend()
only works inside of a fiber, and for that to happen you
must have run it inside of a framework that can schedule and resume these
calls. To reiterate my earlier point, the average PHP developer will not
be in a place where this would ever occur out of the blue for them. It's
not going to surprise them, and even though it might not have an await
or
yield
keyword in front of them, the developer cannot be unaware that they
are inside an event loop that can resume fibers.
I am arguing against you saying this RFC is "very dangerous", because this
feature can only be dangerous if you use it. It's like saying exec()
is
very dangerous, because you can screw up all sorts of things with it. But
it is only dangerous if you use it without knowing what you are doing.
Thanks,
Peter
Hi Peter,
Thanks for clarifying.
Note the difference between the two. Also note how, in both of the
above cases, the asynchronicity is explicit and the developer has
opted into it. Both of the above are different approaches to that
being proposed in this RFC (this is a design choice by the authors).Hi again Josh,
I think we are jumping back and forth on two different things. One is the race condition caused by async, and the other is if the top level code explicitly states that it is called asynchronously.
When I used the Guzzle
requestAsync()
example, it was meant to show that you can have a library do something, and then continue execution like it had completed when in fact it had not. This could cause yoursetTransactionId()
to happen before thecapturePayment()
request has completed, and in that regard it can be the same; not by how it works, but in concept. I do know that they are different in implementation. It would cause this without an explicit keyword showing thatcapturePayment()
used an async call internally. That is what I was referring to when I said it could also be a race condition now, without fibers.As I was also explaining earlier, the developer must know that they are inside an async environment, because you can't suspend the main "thread".
Fiber::suspend()
only works inside of a fiber, and for that to happen you must have run it inside of a framework that can schedule and resume these calls. To reiterate my earlier point, the average PHP developer will not be in a place where this would ever occur out of the blue for them. It's not going to surprise them, and even though it might not have anawait
oryield
keyword in front of them, the developer cannot be unaware that they are inside an event loop that can resume fibers.I am arguing against you saying this RFC is "very dangerous", because this feature can only be dangerous if you use it. It's like saying
exec()
is very dangerous, because you can screw up all sorts of things with it. But it is only dangerous if you use it without knowing what you are doing.Thanks,
Peter
I understand your view; it's the same view that others have expressed
here including the RFC authors. I believe it is fair to paraphrase as,
"If you want to enable fibers in your application, you must be
confident about the implementation details of all of the code in your
application, including that of your dependencies, which are written
and maintained by other developers."
I don't have anything to add to my previous point in that I disagree
that this is practical.
Thanks
"If you want to enable fibers in your application, you must be
confident about the implementation details of all of the code in your
application, including that of your dependencies, which are written
and maintained by other developers."I don't have anything to add to my previous point in that I disagree
that this is practical.
While I agree that this is extremely difficult, and slows adoption of
asynchronous technologies, I think the challenge is not identifying
asynchronous code, it's identifying shared state.
In your example, you show code that was written to use shared state
unwittingly calling code that was written to be asynchronous:
private function capturePayment()
{
$paymentRequest = preparePaymentRequest($this->currentOrder);
$this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}
However, the same problem exists the other way around - code written to
be asynchronous unwittingly calling code written to use shared state:
private async function capturePayment()
{
$paymentRequest = $this->someDependency->preparePaymentRequest();
await $this->paymentGateway->capturePayment($paymentRequest);
$this->someDependency->setTransactionId($paymentRequest->getTransactionId());
}
This all looks fine - but what if someDependency is actually calling
into a library which stores the current order in a static variable? Now
you have exactly the same race condition for the opposite reason. And
the solution is the same: carefully vet all your dependencies.
I can think of a few ways of solving this:
-
Require all the code to be synchronous. This is easy in PHP, even if
Fibers are supported: just don't run in an asynchronous framework. -
Require most of the code to be synchronous. This is the common
approach of labelling functions as "async" or converting return values
to Generators or Promises. The big disadvantage is that it requires
rewriting a lot of code that doesn't care one way or the other if it's
called synchronously. -
Require all the code to be free of shared state. This is ultimately
the only way you'll get the full advantage of asynchronous code. -
Require most of the code to be free of shared state. Having some
primitives in the language to mark out code that definitely can't be
asynchronous would probably be useful. Perhaps you could mark a function
as "no-interrupt"; this could then be used as a wrapper when calling
into a library you know or suspect of using state in unsafe ways.
Perhaps we could rather make fibersopt in at thecallsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem.
Although this would avoid keeping both synchronous and asynchronous
versions of the same function, it would require adding that keyword to
every single function call, just in case somewhere inside it wants to
take advantage of your asynchronous environment.
From my limited understanding, goroutines are a completely different
concept. Saying "go someFunction()" in Go immediately starts a new
thread-like thing, and doesn't return anything. The runtime manages the
scheduling of the thread, but if you want to get any data out of the
goroutine, you have to pass it explicitly, e.g. via a channel.
Regards,
--
Rowan Tommins
[IMSoP]
"If you want to enable fibers in your application, you must be
confident about the implementation details of all of the code in your
application, including that of your dependencies, which are written
and maintained by other developers."I don't have anything to add to my previous point in that I disagree
that this is practical.While I agree that this is extremely difficult, and slows adoption of asynchronous technologies, I think the challenge is not identifying asynchronous code, it's identifying shared state.
In your example, you show code that was written to use shared state unwittingly calling code that was written to be asynchronous:
private function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder);
$this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}However, the same problem exists the other way around - code written to be asynchronous unwittingly calling code written to use shared state:
private async function capturePayment() { $paymentRequest = $this->someDependency->preparePaymentRequest(); await $this->paymentGateway->capturePayment($paymentRequest);
$this->someDependency->setTransactionId($paymentRequest->getTransactionId());
}This all looks fine - but what if someDependency is actually calling into a library which stores the current order in a static variable? Now you have exactly the same race condition for the opposite reason. And the solution is the same: carefully vet all your dependencies.
I can think of a few ways of solving this:
Require all the code to be synchronous. This is easy in PHP, even if Fibers are supported: just don't run in an asynchronous framework.
Require most of the code to be synchronous. This is the common approach of labelling functions as "async" or converting return values to Generators or Promises. The big disadvantage is that it requires rewriting a lot of code that doesn't care one way or the other if it's called synchronously.
Require all the code to be free of shared state. This is ultimately the only way you'll get the full advantage of asynchronous code.
GoLang uses goroutines for this.
Goroutines allow code written by responsible developers for use by others to ensure their packages are safe for consumption by others. The Go mantra related to concurrency is "Do not communicate by sharing memory; instead, share memory by communicating."
https://blog.golang.org/codelab-share
Having experience with Go, channels work brilliantly for allowing concurrent routines access to the same data, albeit in a controlled manner.
- Require most of the code to be free of shared state. Having some primitives in the language to mark out code that definitely can't be asynchronous would probably be useful. Perhaps you could mark a function as "no-interrupt"; this could then be used as a wrapper when calling into a library you know or suspect of using state in unsafe ways.
Perhaps we could rather make fibersopt in at thecallsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem.Although this would avoid keeping both synchronous and asynchronous versions of the same function, it would require adding that keyword to every single function call, just in case somewhere inside it wants to take advantage of your asynchronous environment.
From my limited understanding, goroutines are a completely different concept. Saying "go someFunction()" in Go immediately starts a new thread-like thing, and doesn't return anything. The runtime manages the scheduling of the thread, but if you want to get any data out of the goroutine, you have to pass it explicitly, e.g. via a channel.
Just in case it is relevant for anyone reading this discussion who is not familiar with Go this short article compares and contrasts goroutines vs. threads:
https://www.geeksforgeeks.org/golang-goroutine-vs-thread/
#fwiw
-Mike
HI Rowan,
Thanks for sharing your thoughts.
"If you want to enable fibers in your application, you must be
confident about the implementation details of all of the code in your
application, including that of your dependencies, which are written
and maintained by other developers."I don't have anything to add to my previous point in that I disagree
that this is practical.While I agree that this is extremely difficult, and slows adoption of
asynchronous technologies, I think the challenge is not identifying
asynchronous code, it's identifying shared state.
I agree. If we take it back to first principles, so to speak, then the
problems all involve shared (mutable) state. Thanks for highlighting
that.
Perhaps focusing on shared mutable state might be helpful in
identifying more popular and even more effective solutions to the kind
of problems I'm concerned about. I.e. perhaps solutions which
target/reduce/identify mutability via language features or static
analysis might be more elegant, more effective, and almost certainly
more popular (if added via new language features) than solutions which
rather make it harder to utilise fibers.
If developers could identify that their program contains only a few
hundred state mutations (and they could see where they are), then I
think reviewing and understanding those mutations asks something a bit
more realistic of developers than reviewing and understanding the
internals of their entire codebase.
Having said that, it does seem like it would be very challenging to
really encourage strict immutability at the language level in PHP
given we lack most of the requisite building blocks, such as;
ergonomic higher order functions, immutable data structures, generic
data structures, local constants, etc. I suppose static analysis is a
more realistic place to attack these problems, although that approach
has various drawbacks.
In your example, you show code that was written to use shared state
unwittingly calling code that was written to be asynchronous:private function capturePayment() { $paymentRequest = preparePaymentRequest($this->currentOrder);
$this->paymentGateway->capturePayment($paymentRequest);
$this->currentOrder->setTransactionId($paymentRequest->getTransactionId());
}However, the same problem exists the other way around - code written to
be asynchronous unwittingly calling code written to use shared state:private async function capturePayment() { $paymentRequest = $this->someDependency->preparePaymentRequest(); await $this->paymentGateway->capturePayment($paymentRequest);
$this->someDependency->setTransactionId($paymentRequest->getTransactionId());
}This all looks fine - but what if someDependency is actually calling
into a library which stores the current order in a static variable? Now
you have exactly the same race condition for the opposite reason. And
the solution is the same: carefully vet all your dependencies.I can think of a few ways of solving this:
Require all the code to be synchronous. This is easy in PHP, even if
Fibers are supported: just don't run in an asynchronous framework.Require most of the code to be synchronous. This is the common
approach of labelling functions as "async" or converting return values
to Generators or Promises. The big disadvantage is that it requires
rewriting a lot of code that doesn't care one way or the other if it's
called synchronously.Require all the code to be free of shared state. This is ultimately
the only way you'll get the full advantage of asynchronous code.Require most of the code to be free of shared state. Having some
primitives in the language to mark out code that definitely can't be
asynchronous would probably be useful. Perhaps you could mark a function
as "no-interrupt"; this could then be used as a wrapper when calling
into a library you know or suspect of using state in unsafe ways.
Niklas has suggested something similar as far as I understand. Some
other people have suggested that vendors could somehow declare at the
package level that they are ~"fiber safe" (perhaps in composer.json).
Perhaps we could rather make fibersopt in at thecallsite
(similar to goroutine calls) in order to prevent functions
unexpectedly being executed asynchronously due to faraway changes.
This would be safe and predictable while also avoiding the "What color
is your function" problem.Although this would avoid keeping both synchronous and asynchronous
versions of the same function, it would require adding that keyword to
every single function call, just in case somewhere inside it wants to
take advantage of your asynchronous environment.From my limited understanding, goroutines are a completely different
concept. Saying "go someFunction()" in Go immediately starts a new
thread-like thing, and doesn't return anything. The runtime manages the
scheduling of the thread, but if you want to get any data out of the
goroutine, you have to pass it explicitly, e.g. via a channel.Regards,
--
Rowan Tommins
[IMSoP]--
To unsubscribe, visit: https://www.php.net/unsub.php
Thanks for taking the time to share your thoughts. I found them very
insightful and helpful.
As a side note, GitHub published a blog post a couple of days ago
which provides an interesting real world example of this kind of issue
if people are interested.
https://github.blog/2021-03-18-how-we-found-and-fixed-a-rare-race-condition-in-our-session-handling/
Cheers
Hi,
Guzzle's requestAsync() returns a promise, it does not
interrupt/suspend the callsite. For example:
// this function is not interrupted/suspended -- it will return
synchronously
function doSomething() {
$this->guzzle->requestAsync(...)->then(... handle response here
...);
echo "This will be printed before a response is received";
}The following is similar to how one would implement an coroutine in
PHP today when using a library which implements a coroutine mechanism,
such as amphp. Note the yield statement which interrupts/suspends the
function:// this function will be suspended while the request is in flight
-- it will return after a response is received
function doSomething()
$response = yield $this->guzzle->requestAsync(...);
// do something with response here
echo "This will be printed AFTER the response comes back";
}Note the difference between the two. Also note how, in both of the
above cases, the asynchronicity is explicit and the developer has
opted into it. Both of the above are different approaches to that
being proposed in this RFC (this is a design choice by the authors).
At the risk of sounding dumb: What would that code look like with fibers?
Thanks,
--
Guilliam Xavier
On Thu, Mar 18, 2021 at 1:55 PM Guilliam Xavier
guilliam.xavier@gmail.com wrote:
Hi,
Guzzle's requestAsync() returns a promise, it does not
interrupt/suspend the callsite. For example:// this function is not interrupted/suspended -- it will return
synchronously
function doSomething() {
$this->guzzle->requestAsync(...)->then(... handle response here ...);
echo "This will be printed before a response is received";
}The following is similar to how one would implement an coroutine in
PHP today when using a library which implements a coroutine mechanism,
such as amphp. Note the yield statement which interrupts/suspends the
function:// this function will be suspended while the request is in flight
-- it will return after a response is received
function doSomething()
$response = yield $this->guzzle->requestAsync(...);
// do something with response here
echo "This will be printed AFTER the response comes back";
}Note the difference between the two. Also note how, in both of the
above cases, the asynchronicity is explicit and the developer has
opted into it. Both of the above are different approaches to that
being proposed in this RFC (this is a design choice by the authors).At the risk of sounding dumb: What would that code look like with fibers?
Thanks,
--
Guilliam Xavier
Hi Guilliam,
With fibers, a non-blocking call to Guzzle would look exactly the same
as a blocking call.
function doSomething()
$response = $this->guzzle->request(...);
// do something with response here
echo "This will always be printed AFTER the response comes back";
}
Whether request() and therefore (doSomething()) blocks the whole
process or merely suspends the current fiber would depend on whether
or not doSomething() was called within a fiber, and whether Guzzle had
fiber support, which would be defined elsewhere.
Cheers
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
This is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?
Hey Levi,
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 PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?
How much time do you think you need?
I'd be open to an extension if others feel the same way, but I'm not sure
how much difference it makes given the RFC would currently pass also with
your no vote.
Best,
Niklas
Hey Levi,
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 PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.
I'd be open to an extension if others feel the same way, but I'm not sure how much difference it makes given the RFC would currently pass also with your no vote.
This is true. Unless some of the 46 "yes" voters flip, it seems
unlikely that we'd have more than 10 "no" voters turn up in 3 days, it
seems unlikely to affect the overall result. Still, I would feel
happier knowing I voted one way or another after thorough evaluation,
and not a quick check and gut feeling. This RFC seems like it could
really positively or negatively affect the ecosystem, more so than
most other RFCs, and so I'd like more time if possible.
Hey Levi,
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 PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.
This is fine with me. Let's extend voting for about another week, ending on 3/28 at about 11 PM EDT.
Thanks!
Aaron Piotrowski
On Mar 19, 2021, at 5:47 PM, Levi Morrison levi.morrison@datadoghq.com
wrote:On Fri, Mar 19, 2021 at 3:54 PM Niklas Keller <me@kelunik.com <mailto:
me@kelunik.com>> wrote:Hey Levi,
On Mon, Mar 8, 2021 at 12:40 PM Aaron Piotrowski aaron@trowski.com
wrote:Greetings everyone!
The vote has started on the fiber RFC:
https://wiki.php.net/rfc/fibers https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week, ending
on 3/28 at about 11 PM EDT.
I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and must
not be changed during the vote.
(Not that I care personally, but you would take the risk of the vote being
invalidated...)
--
Guilliam Xavier
On Mon, Mar 22, 2021 at 9:13 AM Guilliam Xavier
guilliam.xavier@gmail.com wrote:
Hey Levi,
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 PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week, ending on 3/28 at about 11 PM EDT.
I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and must not be changed during the vote.
(Not that I care personally, but you would take the risk of the vote being invalidated...)
--
Guilliam Xavier
We should dig through the history, because the line before that is in conflict:
Votes should be open for two weeks at minimum, at the authors discretion this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must not be changed during the vote.
We should dig through the history, because the line before that is in conflict:
Votes should be open for two weeks at minimum, at the authors discretion this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must not be changed during the vote.
I don't think there's a conflict there; there's two separate requirements:
- The duration must be at least two weeks, but may be longer.
- The duration must be specified before the vote starts.
The phrase "may be extended" is referring to who can make the
decision, not when they can make it.
Regards,
--
Rowan Tommins
[IMSoP]
We should dig through the history, because the line before that is in conflict:
Votes should be open for two weeks at minimum, at the authors discretion this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must not be changed during the vote.I don't think there's a conflict there; there's two separate requirements:
- The duration must be at least two weeks, but may be longer.
- The duration must be specified before the vote starts.
The phrase "may be extended" is referring to who can make the
decision, not when they can make it.Regards,
--
Rowan Tommins
[IMSoP]--
To unsubscribe, visit: https://www.php.net/unsub.php
I disagree that it is unambiguous. You missed the important part (to
me, at least), though: what is the history for this edit? Why was it
made? I do not recall discussing this formally at any point (but of
course, I may have missed it or forgot). Quick check on version
history says 2 years ago.
On Mon, Mar 22, 2021 at 9:13 AM Guilliam Xavier
guilliam.xavier@gmail.com wrote:Hey Levi,
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 PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week, ending on 3/28 at about 11 PM EDT.
I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and must not be changed during the vote.
(Not that I care personally, but you would take the risk of the vote being invalidated...)
--
Guilliam XavierWe should dig through the history, because the line before that is in conflict:
Votes should be open for two weeks at minimum, at the authors discretion this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must not be changed during the vote.
I interpret that line to mean that the author may decide to extend the
voting period prior to declaring the valid voting period when voting is
started.
I also cannot find anything in the rules that allows for the author
canceling an ongoing vote, but I believe we’ve done that in the past.
Cheers,
Ben
I also cannot find anything in the rules that allows for the author
canceling an ongoing vote, but I believe we’ve done that in the past.
Maybe this mention in https://wiki.php.net/rfc/howto (not sure it's
authoritative though)?
- Based on the result of the votes and the discussion there are three
possible outcomes:
- Your RFC is accepted: [...]
- Your RFC is declined: [...]
- A serious issue with your RFC needs to be addressed: update the
status of your RFC page and its section on https://wiki.php.net/RFC to
“Under Discussion” and continue again from step 5.
(where "step 5" refers to the discussion phase)
Regards,
--
Guilliam Xavier
On Mon, Mar 22, 2021 at 4:38 PM Levi Morrison levi.morrison@datadoghq.com
wrote:
On Mon, Mar 22, 2021 at 9:13 AM Guilliam Xavier
guilliam.xavier@gmail.com wrote:On Sat, Mar 20, 2021 at 3:06 PM Aaron Piotrowski aaron@trowski.com
wrote:On Mar 19, 2021, at 5:47 PM, Levi Morrison <
levi.morrison@datadoghq.com> wrote:On Fri, Mar 19, 2021 at 3:54 PM Niklas Keller <me@kelunik.com
mailto:me@kelunik.com> wrote:Hey Levi,
On Mon, Mar 8, 2021 at 12:40 PM Aaron Piotrowski aaron@trowski.com
wrote:Greetings everyone!
The vote has started on the fiber RFC:
https://wiki.php.net/rfc/fibers https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron PiotrowskiThis is selfish, but I would like to kindly request lengthening the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week,
ending on 3/28 at about 11 PM EDT.I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and must
not be changed during the vote.(Not that I care personally, but you would take the risk of the vote
being invalidated...)--
Guilliam XavierWe should dig through the history, because the line before that is in
conflict:Votes should be open for two weeks at minimum, at the authors discretion
this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must
not be changed during the vote.
The history is https://wiki.php.net/rfc/abolish-short-votes, but I don't
think it conflicts: to my understanding, what "may be extended" is the
chosen duration vs the minimum duration (e.g. the author can chose to open
a vote for an "extended" 4-weeks period instead of 2-weeks), and that
choice must be set before starting.
Arguably the wording is maybe not the clearest, but there's also this from <
https://externals.io/message/104860>:
+1, but it should probably be possible to extend the voting period once
started, but not shorten it. This allows for extension during holidays in
case the author didn't think about that when starting the vote.Allowing the extension of voting leaves us open to someone extending the
voting period simply because they don't feel like they have the result they
wanted.
Anyway I just wanted to warn (it would be a shame to see the vote result
being debated after an extra week), but that may be OK to the "deciders".
Regards,
--
Guilliam Xavier
On Mon, 22 Mar 2021 at 16:01, Guilliam Xavier guilliam.xavier@gmail.com
wrote:
On Mon, Mar 22, 2021 at 4:38 PM Levi Morrison <levi.morrison@datadoghq.com
wrote:
On Mon, Mar 22, 2021 at 9:13 AM Guilliam Xavier
guilliam.xavier@gmail.com wrote:On Sat, Mar 20, 2021 at 3:06 PM Aaron Piotrowski aaron@trowski.com
wrote:On Mar 19, 2021, at 5:47 PM, Levi Morrison <
levi.morrison@datadoghq.com> wrote:On Fri, Mar 19, 2021 at 3:54 PM Niklas Keller <me@kelunik.com
mailto:me@kelunik.com> wrote:Hey Levi,
On Mon, Mar 8, 2021 at 12:40 PM Aaron Piotrowski <
aaron@trowski.com>
wrote:Greetings everyone!
The vote has started on the fiber RFC:
https://wiki.php.net/rfc/fibers https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron PiotrowskiThis is selfish, but I would like to kindly request lengthening
the
voting window to allow me more time to play with it. I feel like I
can't vote "yes" on something like this without more experience
with
it (which is why I currently have voted "no"). I hope others would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week,
ending on 3/28 at about 11 PM EDT.I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and
must
not be changed during the vote.(Not that I care personally, but you would take the risk of the vote
being invalidated...)--
Guilliam XavierWe should dig through the history, because the line before that is in
conflict:Votes should be open for two weeks at minimum, at the authors
discretion
this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must
not be changed during the vote.The history is https://wiki.php.net/rfc/abolish-short-votes, but I don't
think it conflicts: to my understanding, what "may be extended" is the
chosen duration vs the minimum duration (e.g. the author can chose to open
a vote for an "extended" 4-weeks period instead of 2-weeks), and that
choice must be set before starting.Arguably the wording is maybe not the clearest, but there's also this from
<
https://externals.io/message/104860>:+1, but it should probably be possible to extend the voting period once
started, but not shorten it. This allows for extension during holidays in
case the author didn't think about that when starting the vote.Allowing the extension of voting leaves us open to someone extending the
voting period simply because they don't feel like they have the result they
wanted.Anyway I just wanted to warn (it would be a shame to see the vote result
being debated after an extra week), but that may be OK to the "deciders".Regards,
--
Guilliam Xavier
On Mon, 22 Mar 2021 at 16:01, Guilliam Xavier guilliam.xavier@gmail.com
wrote:On Mon, Mar 22, 2021 at 4:38 PM Levi Morrison <
levi.morrison@datadoghq.com>
wrote:On Mon, Mar 22, 2021 at 9:13 AM Guilliam Xavier
guilliam.xavier@gmail.com wrote:On Sat, Mar 20, 2021 at 3:06 PM Aaron Piotrowski aaron@trowski.com
wrote:On Mar 19, 2021, at 5:47 PM, Levi Morrison <
levi.morrison@datadoghq.com> wrote:On Fri, Mar 19, 2021 at 3:54 PM Niklas Keller <me@kelunik.com
mailto:me@kelunik.com> wrote:Hey Levi,
On Mon, Mar 8, 2021 at 12:40 PM Aaron Piotrowski <
aaron@trowski.com>
wrote:Greetings everyone!
The vote has started on the fiber RFC:
https://wiki.php.net/rfc/fibers https://wiki.php.net/rfc/fibersVoting will run through March 22nd.
Cheers,
Aaron PiotrowskiThis is selfish, but I would like to kindly request lengthening
the
voting window to allow me more time to play with it. I feel like
I
can't vote "yes" on something like this without more experience
with
it (which is why I currently have voted "no"). I hope others
would
play with it more as well if we had more time. Any objections?How much time do you think you need?
Another week seems reasonable; enough time to evaluate it more
thoroughly but not delay things seriously.This is fine with me. Let's extend voting for about another week,
ending on 3/28 at about 11 PM EDT.I'm afraid you can't: from https://wiki.php.net/rfc/voting#voting
A valid voting period must be declared when voting is started and
must
not be changed during the vote.(Not that I care personally, but you would take the risk of the vote
being invalidated...)--
Guilliam XavierWe should dig through the history, because the line before that is in
conflict:Votes should be open for two weeks at minimum, at the authors
discretion
this may be extended, for example during holiday periods.
A valid voting period must be declared when voting is started and must
not be changed during the vote.The history is https://wiki.php.net/rfc/abolish-short-votes, but I
don't
think it conflicts: to my understanding, what "may be extended" is the
chosen duration vs the minimum duration (e.g. the author can chose to open
a vote for an "extended" 4-weeks period instead of 2-weeks), and that
choice must be set before starting.Arguably the wording is maybe not the clearest, but there's also this
from <
https://externals.io/message/104860>:+1, but it should probably be possible to extend the voting period once
started, but not shorten it. This allows for extension during holidays in
case the author didn't think about that when starting the vote.Allowing the extension of voting leaves us open to someone extending the
voting period simply because they don't feel like they have the result
they
wanted.Anyway I just wanted to warn (it would be a shame to see the vote result
being debated after an extra week), but that may be OK to the "deciders".Regards,
--
Guilliam Xavier
Apologies for the empty email, pressed enter twice too fast for my client...
The thing is that by my recollections votes have already been extended.
Mostly when there has been issues with the mailing list, or some outside
event.
Moreso, I don't think extending a vote will in most cases result in the
outcome
they want (acceptance), but I might be mistaken. In this case however it is
a
bit meaningless as it's already passing.
So I think if there needs to be a discussion about clarifying the voting RFC
document it should be made in a different thread.
Best regards,
George P. Banyard
The thing is that by my recollections votes have already been extended.
Mostly when there has been issues with the mailing list, or some outside
event.Moreso, I don't think extending a vote will in most cases result in the
outcome
they want (acceptance), but I might be mistaken. In this case however it
is a
bit meaningless as it's already passing.
So I think if there needs to be a discussion about clarifying the voting
RFC
document it should be made in a different thread.Best regards,
George P. Banyard
You're right. Sorry, I didn't intend to start a debate (nor to be rude to
Levi), just being probably overly cautious ("better safe than sorry", I
remembered that some people challenged the validity of votes on the basis
of "bureaucratic" arguments in the past, and wanted to avoid that here)...
(In this case I personally find it reasonable, but who am I?)
Just in case, let's record that the result is currently 48:14 ;)
--
Guilliam Xavier
The thing is that by my recollections votes have already been extended.
Mostly when there has been issues with the mailing list, or some outside
event.Moreso, I don't think extending a vote will in most cases result in the
outcome
they want (acceptance), but I might be mistaken. In this case however it
is a
bit meaningless as it's already passing.
So I think if there needs to be a discussion about clarifying the voting
RFC
document it should be made in a different thread.Best regards,
George P. Banyard
You're right. Sorry, I didn't intend to start a debate (nor to be rude to
Levi), just being probably overly cautious ("better safe than sorry", I
remembered that some people challenged the validity of votes on the basis
of "bureaucratic" arguments in the past, and wanted to avoid that here)...
(In this case I personally find it reasonable, but who am I?)Just in case, let's record that the result is currently 48:14 ;)
--
Guilliam Xavier
+1 for extending the voting phase for a week. World will not end. If
anything, everyone will be more confident that the RFC voting results
were the correct choice for further development of async PHP. Even if
one week more would change the voting results, then extending the
voting was a correct choice.
On Fri, 19 Mar 2021 at 20:53, Levi Morrison via internals
internals@lists.php.net wrote:
I hope others would
play with it more as well if we had more time. Any objections?
Yes, I object.
You've been around PHP internals long enough to see the drama has
occurred on other RFCs where people have been
cajoled/pressured/threatened to either suspend votes or withdraw RFCs.
Although this RFC is reasonably free from drama, I think it was wrong
for you to ask for an extension regardless of the current voting. Not
only is it improper on its face, but it sets a bad precedent for more
drama filled RFCs.
cheers
Dan
Ack
btw I would prefer that all RFC votes were longer (e.g. 4 weeks for
all decisions that don't have an external time constraint), but
changing the end time during the vote is bogus.
On Fri, 19 Mar 2021 at 20:53, Levi Morrison via internals
internals@lists.php.net wrote:I hope others would
play with it more as well if we had more time. Any objections?Yes, I object.
You've been around PHP internals long enough to see the drama has
occurred on other RFCs where people have been
cajoled/pressured/threatened to either suspend votes or withdraw RFCs.
I agree. I think it puts the RFC author is a bad position too since they
risk upsetting others no matter what they choose to do.
Although this RFC is reasonably free from drama, I think it was wrong
for you to ask for an extension regardless of the current voting. Not
only is it improper on its face, but it sets a bad precedent for more
drama filled RFCs.cheers
Dan
Ackbtw I would prefer that all RFC votes were longer (e.g. 4 weeks for
all decisions that don't have an external time constraint), but
changing the end time during the vote is bogus.--
To unsubscribe, visit: https://www.php.net/unsub.php
--
Chase Peeler
chasepeeler@gmail.com
On Fri, 19 Mar 2021 at 20:53, Levi Morrison via internals
internals@lists.php.net wrote:I hope others would
play with it more as well if we had more time. Any objections?Yes, I object.
You've been around PHP internals long enough to see the drama has
occurred on other RFCs where people have been
cajoled/pressured/threatened to either suspend votes or withdraw RFCs.Although this RFC is reasonably free from drama, I think it was wrong
for you to ask for an extension regardless of the current voting. Not
only is it improper on its face, but it sets a bad precedent for more
drama filled RFCs.cheers
Dan
Ackbtw I would prefer that all RFC votes were longer (e.g. 4 weeks for
all decisions that don't have an external time constraint), but
changing the end time during the vote is bogus.
I agree with Dan. Also, there was plenty of discussion time for this
RFC. It’s not like it was rushed.
Cheers,
Ben
I hope others would
play with it more as well if we had more time. Any objections?Yes, I object.
You've been around PHP internals long enough to see the drama has
occurred on other RFCs where people have been
cajoled/pressured/threatened to either suspend votes or withdraw RFCs.Although this RFC is reasonably free from drama, I think it was wrong
for you to ask for an extension regardless of the current voting. Not
only is it improper on its face, but it sets a bad precedent for more
drama filled RFCs.cheers
Dan
Ackbtw I would prefer that all RFC votes were longer (e.g. 4 weeks for
all decisions that don't have an external time constraint), but
changing the end time during the vote is bogus.I agree with Dan. Also, there was plenty of discussion time for this
RFC. It’s not like it was rushed.
Hey all,
given the wording in the voting rules, the fact that the RFC hasn't been
edited to include the new end date, and due to the objections, I think the
best way forward is closing the voting on the RFC soon. Given no timezone
is mentioned in the RFC, we can probably go with either UTC or UTC-12.
We'll close the vote after UTC-12 passed.
Please create a new thread for discussions about the voting rules in
general that aren't specific for this RFC to keep this thread focused.
Thanks,
Niklas
Hey all,
I've closed the vote and I'm happy to report that the RFC has been accepted
with 78.125% in favor (50:14).
I've moved the RFC to the landing state on
https://wiki.php.net/rfc#pending_implementationlanding
Thank you all for voting and taking part in the discussion!
I'll follow-up once the implementation is merged into core.
Best,
Niklas
Am Mo., 22. März 2021 um 21:08 Uhr schrieb Niklas Keller me@kelunik.com:
I hope others would
play with it more as well if we had more time. Any objections?
Yes, I object.
You've been around PHP internals long enough to see the drama has
occurred on other RFCs where people have been
cajoled/pressured/threatened to either suspend votes or withdraw RFCs.Although this RFC is reasonably free from drama, I think it was wrong
for you to ask for an extension regardless of the current voting. Not
only is it improper on its face, but it sets a bad precedent for more
drama filled RFCs.cheers
Dan
Ackbtw I would prefer that all RFC votes were longer (e.g. 4 weeks for
all decisions that don't have an external time constraint), but
changing the end time during the vote is bogus.I agree with Dan. Also, there was plenty of discussion time for this
RFC. It’s not like it was rushed.Hey all,
given the wording in the voting rules, the fact that the RFC hasn't been
edited to include the new end date, and due to the objections, I think the
best way forward is closing the voting on the RFC soon. Given no timezone
is mentioned in the RFC, we can probably go with either UTC or UTC-12.
We'll close the vote after UTC-12 passed.Please create a new thread for discussions about the voting rules in
general that aren't specific for this RFC to keep this thread focused.Thanks,
Niklas