Stage 1: Memory model and its impact on refactoring #8
Replies: 5 comments 24 replies
-
|
Hi all. Senior software artisan here with 15 years of PHP experience, 8 years of async PHP experience (amphp v2, then v3), 5 years of go experience, 3 years of Rust experience, and much more. My recommendation for async PHP is:
This model matches the status quo in golang and amphp v3: from my 8 years of experience in writing async both business logic and abstraction logic in multiple languages, this is the best concurrency model. Some evidence: I maintain MadelineProto, the biggest PHP MTProto client. MTProto is an async binary protocol over TCP (no HTTP involved), requires heavy caching in order for clients to function correctly, and a lot race-heavy abstractions. MadelineProto is a framework which contains a fully async MTProto client. I migrated MadelineProto to async PHP with amphp v2 (colored, stackless async) in 2018, and then to amphp v3 (colorless, stackful async) in 2022.
Outside in PHP: in 2020, I started writing heavily async business logic in Go, and was very positively surprised by the superior developer experience, especially when using async: I was also very pleased to learn that Go encourages (not forces) the use of the actor model through channels. In my professional Go experience, I wrote heavily concurrent and massively parallel, high-load services, and golang's stackful, colorless approach. I also used Rust to write async business logic, and suffered from the same issues I suffered with amphp v2: large amounts of boilerplate await keywords, heavily impacting UX. To this day, I consider Go's approach superior to that of any other language, confirmed by extensive development experience. |
Beta Was this translation helpful? Give feedback.
-
|
From the PHP Engine side, we can provide developers with additional tools to help detect errors. For example:
The In addition, code safety can be reinforced through a special directive at the package / Composer level. There was also an idea to use a flag in php.ini. This gives us several mechanisms at once to avoid unintended side effects. |
Beta Was this translation helpful? Give feedback.
-
|
Treating WordPress and other code using globals heavily as not target for this proposal is likely path to rejection. It was already expressed by couple of voters that such approach is a no-go (it was in FPM context but I would guess it will be the same here) and if you consider that there are probably some "no" votes just based on the complexity and opinion that this is not needed at all, then I think there is not much chance this could pass. So I think the most likely model to pass is shared nothing. |
Beta Was this translation helpful? Give feedback.
-
|
INI approach is also path to rejection - that will give quite a few "no" votes straight away. |
Beta Was this translation helpful? Give feedback.
-
|
I want to share a few thoughts regarding models 2 and 3. It seems that the shared-nothing model is an absolute winner in terms of safety. I want to point out that this does not come for free. The second memory model (as well as the first, of course) requires manual synchronization from the programmer. The third memory model requires the same as the second. The difference is that shared memory must always be declared explicitly in the language.
I have a classic PHP task that must be solved efficiently.
Each request is handled by a separate coroutine. Memory model 2 answers: Memory model 3 answers: What are the possible solutions for model 3? Readonly classes. Using actors. An actor is a class whose methods are guaranteed to be called only within a single coroutine (at the same time). Actors significantly simplify writing asynchronous code, are thread-safe, and can be freely passed between coroutines. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Stage 1 — Memory model and its impact on refactoring
At this stage of the discussion, I propose focusing on one of the three main questions.
🔑 Key Questions
1. Choosing the Coroutine Model
How coroutines should behave internally:
At the moment, the stackful coroutine model has been chosen, since it allows interaction with C functions and enables mixing C and PHP function calls.
The likelihood of using a different model is low, so this question can be considered resolved.
2. Choosing the Memory Model
How state is managed in asynchronous execution:
The current RFC proposes using the least protected memory model, where coroutines freely share global and static variables.
This question is not resolved and requires further consideration.
The choice of memory model will have a significant impact on the evolution of the language for years to come.
3. Choosing the Runtime Strategy
Defining how async integrates into PHP:
This question will not be discussed at this stage, but it remains important for the consideration of question 2.
🎯 Purpose of Stage 1
The goal of the first discussion stage is to explore the memory model for async execution in PHP.
The memory model has a significant impact on how coroutines will interact with existing PHP code. This is of primary importance. In addition, the memory model determines the direction of the language’s evolution for many years, defining whether a multithreaded model becomes possible or not.
Without resolving this question, we cannot move forward.
Important elements of the discussion can be found here:
https://discourse.thephp.foundation/t/php-dev-vote-true-async-rfc-1-6/4777
Please note the message from
Rowan_Tommins_IMSoP:
https://discourse.thephp.foundation/t/php-dev-vote-true-async-rfc-1-6/4777/75
Possible Memory Models for Coroutines
There are three potential memory models for coroutine execution in PHP:
1. No Memory Separation (current behavior)
Coroutines freely share:
Characteristics:
2. Separated Globals/Statics (objects still shared)
Each coroutine receives:
But:
Status:
3. Full Shared-Nothing Model (maximum isolation)
This model extends option 2 with strict memory isolation:
Rules:
RefCount > 1.Advantages:
Disadvantages:
own) into the language.P.S. Models one and two are used in many languages, including Go. In Go example, developers themselves are responsible for the incorrect use of shared memory.
Beta Was this translation helpful? Give feedback.
All reactions