Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126634 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 446A41A00BC for ; Sat, 8 Mar 2025 08:13:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741421461; bh=U0K6dOnX6M9yImjE9Gstnsj0lhBNASTM0ff2nanuB5Y=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=KjlEVlUa8NLAAgHZWEuJgMR0olVdvWS1JgRCehl4lAHoAUyoBU0LJmpNWQi/E7wnS rhvrH2kxFlWSYfZXISZ0P9NDd6F0qZ3gcIU0ye+gOYEHLHZ+vTqXi6Gb7lwewM/Gxn yPrbzYB9bQyp8+9v977yH6t9AAgt69p0vaHLqdXEEcsQbsTF7FOIJ29EpuxSVGg/P4 fO9u39tPa/vcdRIfNoGvYaziZ84U5aIF9jF8CzjcXrpSg5ZQxXXYcnaDndg8QRzihc 9k2896AhKiSdm0Ikjz3y6XCyB7t8jQBpZ3saf6WV8aTSXcK+ooFhv6yknlfYeCWDa7 S3aLhB1U2hbZg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0EA56180072 for ; Sat, 8 Mar 2025 08:11:01 +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=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (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 ; Sat, 8 Mar 2025 08:11:00 +0000 (UTC) Received: from phl-compute-11.internal (phl-compute-11.phl.internal [10.202.2.51]) by mailfout.stl.internal (Postfix) with ESMTP id A134311400BF; Sat, 8 Mar 2025 03:13:35 -0500 (EST) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-11.internal (MEProxy); Sat, 08 Mar 2025 03:13:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1741421615; x= 1741508015; bh=U0K6dOnX6M9yImjE9Gstnsj0lhBNASTM0ff2nanuB5Y=; b=q y9SV4uxGbK1IIBLng+ttzhOuIzFSrnvXSP1LgGTkcf341Dntxw91KwgZTaSKcUJY YfPPYBD0+k1MFw7pTrd5rYL/9Ep9uU4o0BvsMGZpo2vK8HPwbsyTbbj7V+7Ra8kx urVIOK+rJqa51+rJP7TASVlkugqOEfr2HGHoAsVW+uazQ0ZVk4wXitFTguhLAXKU 14C1FZzo+A2doFw7c77L6IzXbIr+qWoAMgPp0KcVZDl7+b3y+ae/+AxXIipucS6V r1UG26+pIJrDlAw9Vc2o2CXuVv/GyT8BVjTN1T4s8bwWOnNcnZURCdwC7Udpi6lz BBo1AqO/pW2VfEbe4Njfw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1741421615; x=1741508015; bh=U0K6dOnX6M9yImjE9Gstnsj0lhBNASTM0ff 2nanuB5Y=; b=uiNVVmDdCeMkzgKp+eu1OJu0gn7xufuh+fHhMCfZ/MmVFzPs+Df 1gt0Ek3OtrF81G4Orux6zjNGxDbtALeFPg56LEkf33jwS30wIUWL4POfskE9/KVb Seo3rqTCAMBFh5IC+K7tctRpWmfIbL9bImnRxytikKaw5vbBYxdL7m45jcBV9GQS cBzFNNDi0PipYWXGF3r025guVyxmBQ4HNBMTzLsn7tfbQYYMEPvmIJxr82Wmcvz1 dmkg5J8CbdbaNTNiLGZhIZIFb293GiDe6T7qPqU28bu4HPp3S2RpNek1Re9qOxHh MaqW9xa7RSfXagsrM4lFKWQsl+EcD6+RiDg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdduudeftdegucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvfevkfgjfhfutgesrgdtreerredt jeenucfhrhhomhepfdftohgsucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurd gtohguvghsqeenucggtffrrghtthgvrhhnpefhuefhleelheegudefjefgtdejgedvieet ueekgfdtvdeuudekieevudfgjedvkeenucffohhmrghinhepshhtuhhffhifihhthhhsth hufhhfrdgtohhmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhf rhhomheprhhosgessghothhtlhgvugdrtghouggvshdpnhgspghrtghpthhtohepvddpmh houggvpehsmhhtphhouhhtpdhrtghpthhtohepiihsihguvghlnhhikhesghhmrghilhdr tghomhdprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 1446C780068; Sat, 8 Mar 2025 03:13:34 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Sat, 08 Mar 2025 09:13:14 +0100 To: "Eugene Sidelnyk" Cc: "PHP Internals" Message-ID: <05c426b4-4cea-46c3-9013-aa6cfb8b18b4@app.fastmail.com> In-Reply-To: References: <9964db8c-0ffe-43d5-8246-47fc76b07180@app.fastmail.com> <78a03dd0-fd4a-4f4a-ad8a-37e5704f06fc@app.fastmail.com> <08c8ad0b-e8f4-46e3-99f0-b80748d40b89@app.fastmail.com> <07973EAE-2D83-47A8-8FA0-84286C77C02B@rwec.co.uk> <48d66433-3ae9-4895-8361-7c81a0a3670d@app.fastmail.com> Subject: Re: [PHP-DEV] PHP True Async RFC Content-Type: multipart/alternative; boundary=3eeda7242ac948819183e3214cc849f5 From: rob@bottled.codes ("Rob Landers") --3eeda7242ac948819183e3214cc849f5 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sat, Mar 8, 2025, at 09:06, Eugene Sidelnyk wrote: >>=20 >=20 >> The uncoloring of functions in PHP is probably one of the most annoyi= ng aspects of fibers, IMHO. It's hard to explain unless you've been usin= g them awhile. But, with colored functions, the caller has control over = when the result is waiting on -- it could be now, it could be in a total= ly different part of the program, or not at all. With fibers, the author= of the function you are calling has control over when the result is wai= ted on (and they don't have control over anything they call). This can c= reate unpredictable issues when writing code where a specific part wrote= some code thinking it had exclusive access to a property/variable. Howe= ver, someone else changed one of the functions being called into an asyn= c function, making that assumption no longer true. >>=20 >> With colored functions, the person making changes also has to update = all the places where it is called and can validate any assumptions are s= till going to be true; uncolored functions means they almost never do th= is. This results in more work for people implementing async, but more co= rrect programs overall. >>=20 >> But back to the awaiting on results. Say I want to read 10 files: >>=20 >> for ($i =3D 0; $i < 10; $i++) $results[] =3D file_get_contents($file[= $i]); >>=20 >> Right now, we have to read each file, one at a time, because this is = synchronous. Even with this RFC and being in a fiber, the overall execut= ion might be non-blocking, but the code still reads one file after anoth= er sequentially. Fibers do not change this. >>=20 >> With this RFC (in its original form), we will be able to change it so= that we can run it asynchronously though and choose when to wait: >>=20 >> for($i =3D 0; $i < 10; $i++) $results[] =3D async\async(fn($f) =3D> f= ile_get_contents($f), $file[$i]); >> // convert $results into futures somehow -- though actually doesn't l= ook like it is possible. >> $results =3D async\awaitAll($results); >>=20 >> In that example, we are deliberately starting to read all 10 files at= the same time. If we had colored functions (aka, async/await) then chan= ging file_get_contents to async would mean you have to change everywhere= it is called too. That means I would see that file_get_contents is sync= hronous and be able to optimize it without having to even understand the= reasoning (in most cases). I was a user of C# when this happened to C#,= and it was a pain... So, at least with PHP fibers, this won't be AS pai= nful, but you still have to do some work to take full advantage of them. >>=20 >> I kind of like the idea of a nursery for async, as we could then upda= te file_get_content's return type to something like string|false|future<= string|false>. In non-async, you have everything behave as normal, but i= nside a nursery, it returns a future that can be awaited however you wan= t and is fully non-blocking. In other words, simply returning a future i= s enough for the engine to realize it should spawn a fiber (similar to h= ow using yield works with generators).=20 >>=20 >> In any case, I believe that a nursery requires the use of colored fun= ctions. That may be good or bad, but IMHO makes it much more useful and = easier to write correct and fast code. >>=20 >=20 >=20 > In my opinion, colored functions is the worst thing that could happen = to PHP. >=20 > https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-funct= ion > Describes quite expressively what's wrong about this approach. >=20 > As the result, you will make everything async. > Want a repository? It will be all async. > Want a logger? Also async. > Need to cache something? Make it async. >=20 > This is going to be a ton of changes, when currently sync (blue functi= on) will have to become async (red one). >=20 > The way amphp goes - it's the right way. They have had this problem of= red-blue functions a long ago until Fibers came into place. >=20 > What they used until third version is generator-based coroutines, so t= hat instead of returning actual object, you spoil the signature of the f= unction and return generator that will return that object (iow, "Promise= "). >=20 > This is just annoying, and IMO should not be considered. My point in the email is that this happens anyway. With colored function= s, you /*always/* decide how to handle async. Which, as you mentioned, c= an be annoying. With uncolored functions, you */never/* get to decide un= less you wrap it in a specific form (async\run or async\async, in this R= FC), which ironically colors the function. I can't think of any way arou= nd it. My biggest issue with this RFC is that it results in **multiple**= colors: FiberHandle, Future, and Resume.=20 =E2=80=94 Rob --3eeda7242ac948819183e3214cc849f5 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

=
On Sat, Mar 8, 2025, at 09:06, Eugene Sidelnyk wrote:
=
<= div>


The uncoloring of= functions in PHP is probably one of the most annoying aspects of fibers= , IMHO. It's hard to explain unless you've been using them awhile. But, = with colored functions, the caller has control over when the result is w= aiting on -- it could be now, it could be in a totally different part of= the program, or not at all. With fibers, the author of the function you= are calling has control over when the result is waited on (and they don= 't have control over anything they call). This can create unpredictable = issues when writing code where a specific part wrote some code thinking = it had exclusive access to a property/variable. However, someone else ch= anged one of the functions being called into an async function, making t= hat assumption no longer true.

With colored= functions, the person making changes also has to update all the places = where it is called and can validate any assumptions are still going to b= e true; uncolored functions means they almost never do this. This result= s in more work for people implementing async, but more correct programs = overall.

But back to the awaiting on result= s. Say I want to read 10 files:

for ($i =3D= 0; $i < 10; $i++) $results[] =3D file_get_contents($file[$i]);

Right now, we have to read each file, one at a t= ime, because this is synchronous. Even with this RFC and being in a fibe= r, the overall execution might be non-blocking, but the code still reads= one file after another sequentially. Fibers do not change this.

With this RFC (in its original form), we will be a= ble to change it so that we can run it asynchronously though and choose = when to wait:

for($i =3D 0; $i < 10; $i+= +) $results[] =3D async\async(fn($f) =3D> file_get_contents($f), $fil= e[$i]);
// convert $results into futures somehow -- though= actually doesn't look like it is possible.
$results =3D a= sync\awaitAll($results);

In that example, w= e are deliberately starting to read all 10 files at the same time. If we= had colored functions (aka, async/await) then changing file_get_content= s to async would mean you have to change everywhere it is called too. Th= at means I would see that file_get_contents is synchronous and be able t= o optimize it without having to even understand the reasoning (in most c= ases). I was a user of C# when this happened to C#, and it was a pain...= So, at least with PHP fibers, this won't be AS painful, but you still h= ave to do some work to take full advantage of them.

I kind of like the idea of a nursery for async, as we could the= n update file_get_content's return type to something like string|false|f= uture<string|false>. In non-async, you have everything behave as n= ormal, but inside a nursery, it returns a future that can be awaited how= ever you want and is fully non-blocking. In other words, simply returnin= g a future is enough for the engine to realize it should spawn a fiber (= similar to how using yield works with generators). 
<= br>
In any case, I believe that a nursery requires the use of = colored functions. That may be good or bad, but IMHO makes it much more = useful and easier to write correct and fast code.



In my opinion, colored functions is t= he worst thing that could happen to PHP.

=
D= escribes quite expressively what's wrong about this approach.
<= div dir=3D"auto">
As the result, you will mak= e everything async.
Want a repository? It wil= l be all async.
Want a logger? Also async.
Need to cache something? Make it async.

This is going to be a to= n of changes, when currently sync (blue function) will have to become as= ync (red one).

Th= e way amphp goes - it's the right way. They have had this problem of red= -blue functions a long ago until Fibers came into place.

What they used until third versi= on is generator-based coroutines, so that instead of returning actual ob= ject, you spoil the signature of the function and return generator that = will return that object (iow, "Promise").
This is just annoying, and IMO should not be co= nsidered.

My point in th= e email is that this happens anyway. With colored functions, you /alw= ays/ decide how to handle async. Which, as you mentioned, can be ann= oying. With uncolored functions, you /never/ get to decide u= nless you wrap it in a specific form (async\run or async\async, in this = RFC), which ironically colors the function. I can't think of any way aro= und it. My biggest issue with this RFC is that it results in *mu= ltiple* colors: FiberHandle, Future, and Resume. 
=E2=80=94 Rob
--3eeda7242ac948819183e3214cc849f5--