Hello everyone!
RFC https://wiki.php.net/rfc/true_async
Here is the seventh version of the RFC, revised and expanded.
Version 1.7 (December 2025)
-
Fiber integration: added
Fiber::getCoroutine()method,
ownership model, deadlock resolution - Added Coroutine methods:
getId(),getResult(),getException(),
getTrace() - Refined Goals section: improved clarity and technical accuracy of
core value propositions - Function naming aligned with PHP coding standards:
currentCoroutine()→current_coroutine(),
gracefulShutdown()→shutdown(),
getCoroutines()→get_coroutines() - Method renaming:
Coroutine::onFinally()→Coroutine::finally()(brevity) - Interface renaming:
FutureLike→Completable - Exception renaming:
CancellationError→Cancellation(clearer semantics) - Moved
Cancellationto the root namespace (\Cancellation) as
a fundamental PHP mechanism - Changed
Cancellationinheritance from\Errorto\Throwable,
following Python’sCancelledErrorpattern - Added backward compatibility notes for the new root namespace class
- Renamed
DeadlockExceptiontoDeadlockCancellation
My Comments
Since the vote took place, I have tried to bring together specialists
in asynchronous programming to discuss the RFC, and I was surprised by
the lack of serious disagreements. You can read the discussion on
GitHub, where key opinions from representatives of different libraries
and components are expressed.
These discussions became the basis for refining the RFC.
Compatibility research involving WordPress, Laravel, and AMPHP helped
clarify future prospects and potential challenges.
As part of the research, Xdebug was also adapted, without which
debugging WordPress code in coroutines would have been inconvenient. A
special version of Async-Worker for FrankenPHP was also developed.
Memory models were not included in the RFC because none of them
provide significant benefits, do not make the code noticeably better,
and all of them have drawbacks. Instead, future versions are expected
to introduce a separate API and philosophy for multithreaded
coroutines.
I returned to the original idea of defining the Cancellation exception
directly in the PHP core. This was always the right decision, and it
should not have been abandoned.
The most important change in this RFC is support for fibers as an
extended form of coroutines. It turned out to be a great idea.
I finally came up with a good term to replace FutureLike, which had
been really annoying me.
Experiments
To understand which code breaks, a special version of TrueAsync was
created that made GLOBALS unique per coroutine. This made it possible
to run WordPress as a stateful application with only a few changes.
Two versions of the code were implemented. One where WordPress was
fully initialized in each coroutine for every request, and another
where WordPress cloned only a subset of its data structures. Similar
experiments were also conducted on Laravel.
No more than 1–2 hours were spent on code changes for WordPress and
Laravel. In other words, there were almost no changes.
Automatic analysis of the Laravel codebase showed that the number of
components combining I/O operations with shared in-memory state is
extremely small compared to the amount of code that can work without
changes. Some WordPress functions with static variables continued to
work as before because they did not contain any I/O operations.
Overall, it became clear that the vast majority of the code remains
functional in a concurrent environment and works without changes. This
means that transparent async can actually save developers time and
money.
Key Conclusions
-
One-thread coroutines are a powerful pattern for web-oriented
programming languages, providing a balanced trade-off between system
complexity, code safety, and developer ergonomics. -
Coroutines running in other threads do not contradict the
one-thread model. They require further development and can integrate
organically, complementing each other’s functionality. -
Actors are likely to become the next key pattern for
multithreaded programming. Their implementation is clear, feasible,
efficient, and surprisingly safe. -
Memory isolation and transfer mechanisms between PHP threads
will not conflict with the current RFC. Instead, they will complement
it and coexist alongside it.
I think having two tools for async, concurrent coroutines and
inter-thread interaction, can complement each other very well, and
most importantly, they can be built gradually, step by step.
This is, of course, a brief summary of the events of the past month,
so if I missed anything, please feel free to ask.
Merry Christmas to everyone!
Hi everyone.
I have completed the research on PHP core changes for multithreaded
programming. The article briefly presents the main benefits of PHP
multithreading: thread pools and actors.
https://github.com/true-async/multithreaded-php/blob/main/mm-en.md
This research makes it possible to look into a potential timeline of
PHP’s evolution and imagine how the current RFC could interact with
multithreading abstractions.
The article examines how threads and actors can interact with coroutines.
As for my personal opinion.
I believe that actors are the safest and most sustainable pattern for
the PHP language. They are much better than manual thread management
and better than interacting with a thread pool. PHP should evolve
toward higher-level abstractions that are not tied to OS-specific
details. I am convinced that the presence of low-level APIs in PHP
that mirror C functions is a historical design mistake that should be
phased out.
Actors allow writing sequential code without thinking about
multithreading or thread pools. This is a solid tool with proven
effectiveness and well-known trade-offs, focused on business logic.
That is why actors are a perfect fit for PHP. A single-threaded
coroutine model fits actors very well, creating the necessary illusion
of sequential execution.
The current amount of research, experimentation, and knowledge should
be sufficient to make a well-balanced decision.
Best regards, Ed