Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126573 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id C71BD1A00BC for ; Wed, 5 Mar 2025 09:38:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741167326; bh=AhSy4l6A19oYc1YZvRcmU20CjmoRjqiep+p+PqAKb7s=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=fB1NRNpbMrGZrCu/Up4J/3KrYN3rNnpJ88t5sKln6nH1PCaaCELB30S1t99p+8SK5 Z+3cgY5pSzwwROLXi6+kw9euljQbhNvqayLU9bA8GIRthKWCE5Uk0XEJisBRVp1m7U bkYNqmLW09C69C2/frTH5kLxZBbf38KUDhy7Xw30VGw2fo0fDgMBQ1iXArIwanOzxG dIf/cK9RWtxf1XaiLPAdnHPRReArZXklf31Qy+Mq8R1QZxyoc5cCIaRqQpaP94AHtu m9op6m4esgKPoOGjZgXOkADjItgmQ9nv+MVdVLvXkd+6DTK4jbKhY99XgiFK2sEGt+ sOamJgFavXkUQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4FE2C18004B for ; Wed, 5 Mar 2025 09:35:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f170.google.com (mail-yb1-f170.google.com [209.85.219.170]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 5 Mar 2025 09:35:24 +0000 (UTC) Received: by mail-yb1-f170.google.com with SMTP id 3f1490d57ef6-e53ef7462b6so5520148276.3 for ; Wed, 05 Mar 2025 01:38:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741167480; x=1741772280; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=hgAUaoa4Jm+iAKJlS7UXmjYv5G5mbqgixA6E1AGIk5Y=; b=BurHuRU2dYSxbKSWzOuQHYkls/4o0uCVht1o07OX/3D+BgLK+v7xmq1u7R1KG7Ycx4 XI4xZr916wUvNBveZu3SAot/Q8SEmlgwEmhsX4qH0jc+Hx8/Ee/KHGeS+9nvpnvRPWFj r37tq/ao0ZEgaIhQB6ne5NlRmAVjzgn0m7WWtiICtIpuVohqtNgkArYgqfDF0N0JgHWd 2jiyT5kOfxhMDqCMV/JOcKLra4iHDBfB+NMyEkkzub8HE5LSGAp3KKvzhV8IWJsyauku iSsAUUzRHLsExd6imoLim1AoIyMQ3Gzc/TUn5uJt8DPEj2OhTDiWroEPiNbvhHdBM4Z2 iF0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741167480; x=1741772280; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=hgAUaoa4Jm+iAKJlS7UXmjYv5G5mbqgixA6E1AGIk5Y=; b=g82EjnPwx1Ap1tDThMQzyPG50GHicrxRGkuLzQWihGR+AsAiDAdsBARf+dg6QqODR9 6q2bxIQFGIbQQdHh2z9BTYRsqBueOniP84IMs1F1aGklfwCHW3Ixm0dVkTN6OJspZg5g 4jb5PYH/dv5Hdf8AYgoy6VJGtMUBF6XyyBz5nojIE0O8NFXvpauUGAfnNWoQ7vh4Quuj ExKJpbmkToYSwc8sz/Cn08ByrP4DLYfw1B+/WXB/rI9FgG9/dSQ4zB/G7tbN9DWB8yWa Dr7FeMGvvv247mszwq7ZKqJosJ/WNfoQEBMc+Rg/lFGZYp1YeJUM8NHkJCAFfhM4Egwk Lylw== X-Gm-Message-State: AOJu0Yyosq1jvaSN+/xT6C5tdXVZ89RYVzD5zTedzxLrkTZ7aQyOD9MQ fgJuIhtJKSgntjJhSU8xMgzZsA9DEuyehUe5a9jGiBQ7+k+SuXJtzz5PJ/zOOtJqErU5TZUsFh7 J7P4AygBH8j/VauSOBRscxJWykVK0vytdXKM= X-Gm-Gg: ASbGncvdcJudYWbSA3DU5IqCU9I3BkHL118nLhJMp+9Q7AAzqftEWizGpSME7kCx3AM SdhabDv66b/+dgIQ7RfRxuluW892fr3LBmQh0PclKEAQVzw79gpiji3l+fJupUaB6XbTgRl6WoY 5OKYH6nclOe2Qdm0t1cEnBNecz1A== X-Google-Smtp-Source: AGHT+IHLmqB/FSB9rFSyIiAKzyyEln1ovkAlynMvP+W/7QFz2Gyi1+/OYE0dyiY+lVWOLiFKvOOC+NRyO9IYv0n3JdQ= X-Received: by 2002:a05:6902:2a4a:b0:e60:9d12:c1e5 with SMTP id 3f1490d57ef6-e611e30599fmr3333387276.36.1741167480234; Wed, 05 Mar 2025 01:38:00 -0800 (PST) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <9964db8c-0ffe-43d5-8246-47fc76b07180@app.fastmail.com> In-Reply-To: <9964db8c-0ffe-43d5-8246-47fc76b07180@app.fastmail.com> Date: Wed, 5 Mar 2025 11:37:49 +0200 X-Gm-Features: AQ5f1JrBZjV0pMbPcVNmffx_Vk_Umla7x39aV9veXJozSKbTsVCl5IsS8Oa1rbY Message-ID: Subject: Re: [PHP-DEV] PHP True Async RFC To: Larry Garfield Cc: php internals Content-Type: multipart/alternative; boundary="0000000000002782b7062f95251f" From: edmond.ht@gmail.com (Edmond Dantes) --0000000000002782b7062f95251f Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Good day, Larry. > First off, as others have said, thank you for a thorough and detailed proposal. Thanks! > * A series of free-standing functions. > * That only work if the scheduler is active. > * The scheduler being active is a run-once global flag. > * So code that uses those functions is only useful based on a global state not present in that function. > * And a host of other seemingly low-level objects that have a myriad of methods on them that do, um, stuff. > * Oh, and a lot of static methods, too, instead of free-standing functions. Suppose these shortcomings don=E2=80=99t exist, and we have implemented the= boldest scenario imaginable. We introduce Structured Concurrency, remove low-level elements, and possibly even get rid of Future. Of course, there are no functions like startScheduler or anything like that. 1. In this case, how should PHP handle Fiber and all the behavior associated with it? Should Fiber be declared deprecated and removed from the language? What should the flow be? 2. What should be done with I/O functions? Should they remain blocking, with a separate API provided as an extension? 3. Would it be possible to convince the maintainers of XDEBUG and other extensions to rewrite their code to support the new model? ( *If you're reading this question now, please share your opinion.* ) 4. If transparent concurrency is introduced for I/O in point 2, what should be done with Revolt + AMPHP? This would break their code. Should an additional function or option be introduced to switch PHP into "legac= y mode"? I share your feelings on many points, but I would like to see some real-world alternative. > > I commend to your attention this post about a Python async library > Structured concurrency is a great thing. However, I=E2=80=99d like to avoid changing the language syntax and make something closer to Go=E2=80=99s sema= ntics. I=E2=80=99ll think about it and add this idea to my TODO. > async $context { > // $context is an object of AsyncContext, and can be passed around as such. > // It is the *only* way to span anything async, or interact with the async controls. > // If a function doesn't take an AsyncContext param, it cannot control async. This is good. This is a very elegant solution. Theoretically. However, in practice, if you require explicitly passing the context to all functions, it leads to the following consequences: 1. The semantics of all functions increase by one additional parameter (*Signature bloat*). 2. If an asynchronous call needs to be added to a function, and other functions depend on it, then the semantics of all dependent functions mu= st be changed as well. In strict languages, a hybrid model is often used, or like in Go, where the context is passed explicitly as a synchronization object, but only when necessary. In this example, there is another aspect: the fact that async execution is explicitly limited to a specific scope. This is essentially the same as startScheduler, and it is one of the options I was considering. Of course, startScheduler can be replaced with a construction like async(function() { ... }). This means that async execution is only active within the closure, and coroutines can only be created inside that closure. This is one of the semantic solutions that allows removing startScheduler, but at the implementation level, it is exactly the same. What do you think about this? > I'm not convinced that sticking arbitrary key/value pairs into the Context object is wise; Why not? > that's global state by another name Static variables inside a function are also global state. Are you against static variables? > But if we must, the above would handle all the inheritance and override stuff quite naturally. Possibly with: How will a context with open string keys help preserve service data that the service doesn't want to expose to anyone? The Key() solution is essentially the same as Symbol in JS, which is used for the same purpose. Of course, we could add a coroutine static $var construct to the language syntax. But it's all the same just syntactic sugar that would require more code to support. > [$in, $out] =3D Channel::create($buffer_size); This semantics require the programmer to remember that two variables actually point to the same object. If a function has multiple channels, this makes the code quite verbose. Additionally, such channels are inconvenient to store in lists because their structure becomes more complex= . I would suggest a slightly different solution: $in =3D new Channel()->getProducer(); async myFunction($in->getConsumer()); This semantics do not restrict the programmer in usage patterns while still allowing interaction with the channel through a well-defined contract. Thanks for the great examples, and a special thanks for the article. I also like the definition of context. Ed --0000000000002782b7062f95251f Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Good day, Larry.

> First off, as oth= ers have said, thank you for a thorough and detailed proposal.
Th= anks!

> * A series of free-standing functions.<= /div>> * That only work if the scheduler is active.
> * The schedu= ler being active is a run-once global flag.
> * So code that uses tho= se functions is only useful based on a global state not present in that fun= ction.
> * And a host of other seemingly low-level objects that have = a myriad of methods on them that do, um, stuff.
> * Oh, and a lot of = static methods, too, instead of free-standing functions.

Suppose these shortcomings don=E2=80=99t exist, and we have implemented= the boldest scenario imaginable. We introduce Structured Concurrency, remo= ve low-level elements, and possibly even get rid of Future. Of= course, there are no functions like startScheduler or anythin= g like that.

  1. In this case, how should PHP handle Fiber and all the behavior associated with it? Should Fiber be d= eclared deprecated and removed from the language? What should the flow be?<= /li>
  2. What should be done with I/O functions? Should they remain blocking= , with a separate API provided as an extension?
  3. Would it be possibl= e to convince the maintainers of XDEBUG and other extensions to rewrite the= ir code to support the new model? ( If you're reading this question now, please share your opinion. )
  4. If transparent concurrency is introduced for I/O in point 2, what= should be done with Revolt + AMPHP? This would b= reak their code. Should an additional function or option be introduced to s= witch PHP into "legacy mode"?

I share your feelin= gs on many points, but I would like to see some real-world alternative.

=

>=C2=A0
>=C2=A0I commend to your attention this post about a Python async library=C2=A0
>

Structured concurrency is a great thing. However, I=E2=80=99d like to avoid= changing the language syntax and make something closer to Go=E2=80=99s sem= antics. I=E2=80=99ll think about it and add this idea to my TODO.

>= ; async $context {
> // $context is an object of AsyncContext, and ca= n be passed around as such.
> // It is the *only* way to span anythin= g async, or interact with the async controls.
> // If a function does= n't take an AsyncContext param, it cannot control async.=C2=A0 This is = good.

This is a very elegant solution. Theoretically.

However, = in practice, if you require explicitly passing the context to all functions= , it leads to the following consequences:

  1. The semantics of all f= unctions increase by one additional parameter (Signature bloat).
  2. If an asynchronous call needs to be added to a function, and other fun= ctions depend on it, then the semantics of all dependent functions must be = changed as well.=C2=A0

In strict languages, a hybrid model is o= ften used, or like in Go, where the context is passed explicitly as a synch= ronization object, but only when necessary.

In this example, there is another aspect: the fact that async execut= ion is explicitly limited to a specific scope. This is essentially the same= as startScheduler, and it is one of the options I was conside= ring.

Of course, startScheduler can be replaced with a c= onstruction like async(function() { ... }).
This means that= async execution is only active within the closure, and coroutines can only= be created inside that closure.

This is one of the semantic solution= s that allows removing startScheduler, but at the implementati= on level, it is exactly the same.

What do you think about this?

>=C2=A0I'm no= t convinced that sticking arbitrary key/value pairs into the Context object= is=C2=A0wise;=

Why not?=C2=A0

>=C2=A0that's global state by another name

<= p>=C2=A0 Static variables inside a function are also global state. Are you = against static variables?

>=C2=A0But if we must, the above would handle=C2=A0all the inheritance and = override stuff quite naturally. Possibly with:

=C2=A0How will= a context with open string keys help preserve service data that the servic= e doesn't want to expose to anyone? The Key() solution is = essentially the same as Symbol in JS, which is used for the sa= me purpose. Of course, we could add a coroutine static $var co= nstruct to the language syntax. But it's all the same just syntactic su= gar that would require more code to support.=C2=A0

>=C2=A0[$in, $out] =3D Channel::crea= te($buffer_size);

This semantics require the programmer to rem= ember that two variables actually point to the same object. If a function h= as multiple channels, this makes the code quite verbose. Additionally, such= channels are inconvenient to store in lists because their structure become= s more complex.

I would suggest a slightly different solution:

= <code php>
$in =3D new Channel()->getProducer();
async myFun= ction($in->getConsumer());
<code>

This semantics do not r= estrict the programmer in usage patterns while still allowing interaction w= ith the channel through a well-defined contract.=C2=A0=C2=A0

Thanks f= or the great examples, and a special thanks for the article.
I also like= the definition of context.

Ed

--0000000000002782b7062f95251f--