Re: PHP True Async RFC - Stage 2

From: Date: Tue, 18 Mar 2025 07:59:58 +0000
Subject: Re: PHP True Async RFC - Stage 2
References: 1 2  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


On 18 March 2025 05:59:07 GMT, Larry Garfield <[email protected]> wrote:

>My biggest issue, though, is that I honestly can't tell what the mental model is supposed
>to be.  The RFC goes into detail about three different async models.  Are those standard terms
>you're borrowing from elsewhere, or your own creation?  If the former, please include
>citations.  I cannot really tell which one the "playpen" model would fit into.  I... think
>bottom up, but I'm not sure.  Moreover, I then cannot tell which of those models is in use in
>the RFC.  There's a passing reference to it being bottom up, I think, but it certainly looks
>like the No Limit model.  There's a section called structured concurrency, but what it
>describes doesn't look a thing like the playpen-definition of structured concurrency, which as
>noted is my preference.  It's not clear why the various positives and negatives are there;
>it's just presented as though self-evident.  Why does bottom up lead to high memory usage, for
>instance?  That's not clear to me.  So really... I have no idea how to think about any of it.


I had a very different reaction to that section. I do agree that some citations and links to prior
art would be good - I mentioned in my first email that the "actor model" is mentioned in
passing without ever being defined - but in general, I  thought this summary was very succinct:

> -  No limitation. Coroutines are not limited in their lifetime and run as long as needed.
> - Top-down limitation: Parent coroutines limit the lifetime of their children
> - Bottom-up limitation: Child coroutines extend the execution time of their parents

Since you've described playpens as having an implicit "await all", they're
bottom-up: the parent lasts as long as its longest child. Top-down would be the same thing, but with
an implicit "cancel all" instead.


>Broadly speaking, I can think of three usage patterns for async in PHP (speaking, again, as
>someone who doesn't have a lot of async experience, so I may be missing some):
>
>1. Fan-out.  This is the "fetch all these URLs at once" type use case, which in most
>cases could be wrapped up into a para_map() function.  (Which is exactly what Rust does.)
>2. Request handlers, for persistent-process servers.  Would also apply for a queue worker.
>3. Throw it over the wall.  This would be the logging example, or sending an email on some
>trigger, etc.  Importantly, these are cases where there is no result needed from the sub-routine.


I agree that using these as key examples would be good.



>// Creates an async scope, in which you can create coroutines.
>async {


The problem with using examples like this is that it's not clear what happens further down the
stack - are you not allowed to spawn/start/whatever anything? Does it get started in the
"inherited" scope?

You've also done exactly what you complained the RFC did and provided a completely artificial
example - which of the key use cases you identified is this version of scope trying to solve?

I actually think what you're describing is very similar to the RFC, just with different syntax;
but your examples are different, so you're talking past each other a bit.



>I honestly cannot see a use case at this point for starting coroutines in arbitrary scopes.


The way I picture it is mostly about choosing between creating a child within a narrow scope
you've just opened, vs creating a sibling in the scope created somewhere up the stack.

The "request handler" use case could easily benefit from a "pseudo-global" scope
for each request - i e. "tie this to the current request, but not to anything else that's
started a scope in between".

There were also some concrete examples given in the previous thread of explicitly managing a
context/scope/playpen in a library.


Rowan Tommins
[IMSoP]


Thread (59 messages)

« previous php.internals (#126820) next »