Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126561 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 5B51D1A00BC for ; Tue, 4 Mar 2025 18:37:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741113264; bh=m6M4R9qXzE1VpC/f2MeEt4rij4VOlt45u2LU44KcIfI=; h=Date:From:To:In-Reply-To:References:Subject:From; b=il1M883j9bTqDgbbDfxwaQWCbFZHafaDIVQF/nF8QPEoJL4APsN+II4p14Ede4S6s 5q4BpZNZzy78En7vzpvvqHeRag4MrBOpypu78iQn+Eof6C0SubFRkMD4uMo0og6qOj V/Wx7v0NKOFFHod74b+x3jb7a7jjRzlG2CVTAp5LlQ+gYblLOyyjP6QCHjk3q2ONvt agdd+LZQN7n1tsQ/rfc742HtVzFi6iHnWVNu/qYZ+rrYD+mm5XFzPKkO4SpB7aCEIe kJEfAN7IOwoIShN8wFSTSqgy6aQHZiJm8rCb2MDbiGkvC2e2Hcidw0lULKDhrBX/hy nmshMcCh/bKAA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 3A80218006D for ; Tue, 4 Mar 2025 18:34:23 +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.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_NONE,URIBL_SBL_A autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-a8-smtp.messagingengine.com (fhigh-a8-smtp.messagingengine.com [103.168.172.159]) (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 ; Tue, 4 Mar 2025 18:34:22 +0000 (UTC) Received: from phl-compute-04.internal (phl-compute-04.phl.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 7BFA4114019E for ; Tue, 4 Mar 2025 13:36:58 -0500 (EST) Received: from phl-imap-06 ([10.202.2.83]) by phl-compute-04.internal (MEProxy); Tue, 04 Mar 2025 13:36:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding: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=fm1; t=1741113418; x=1741199818; bh=CJkDBX1RBGTbditAiizjb 06DMDkDwYoMAidxt3o7ZYI=; b=LxA9P7XEMujrowzL3cBBmZZmHDhRHevgvthe+ pOm+dBbuwB4KrdK6+JbjvYMyQdrXbnukfQp52wVMB+n3TTpvUShr08cL5STW6550 0o0DL9xwdEFvnXYX1UnfGmGoPvXN4WM4hLgyrnt78D5ErCg0mYZYHuL6xoQ/jQvE bQgMh6h1sHmgAgSwneyYC5GNLLpvXtEPys5zgfN8Zg2rk0EoyGkT4xokOGu/OebO BDn0C1ej/VZtn2FopMnIdOg7oC3P3lJX6A3ysODZBUXP2Ci4mZCIp7mR7+esTdS1 2md2Ba4DHaIA6UMRNL4hUPwvsJKoyddxy6KvPHYeyGfFOOLcA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding: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=1741113418; x=1741199818; bh=C JkDBX1RBGTbditAiizjb06DMDkDwYoMAidxt3o7ZYI=; b=f360/Vm2TkHE5e/Af uxT1gs9csjqR5qnA8aOLdIji352iyvE4Ov//uikrpryq6DFjxXQSnYoNCUhrrkFJ PS6EcNIgeCTxwGrI6Wli07MJKRZTB+zJvaP2yGgg73AglHkHiio81f9UJmIgrzMW X25rKGfuAliNWrK8WYlfOh/tiXQwxwVchAl71za3g0QpQscuHX4nd5UY3oJyDmEy B9EKqcHdFYsTxJFhOjZegLpi3RSDBObuV2wlV414ZbIMqNs9g5hLZZEYnKpjoLgw vKHdHoRVHv93PwdD3kE9r028qttis941AaEjLpqPV5+s438eDJLiwYd/DGlLXG8i Bz91A== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddutddvjeekucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvffkjghfufgtgfesthhqredtredt jeenucfhrhhomhepfdfnrghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrh hfihgvlhguthgvtghhrdgtohhmqeenucggtffrrghtthgvrhhnpefhudefteelfeekleev feehvedujefgffevfedtgfekffekgfejueefhefgffdvgeenucffohhmrghinhepphhhph drnhgvthdpvhhorhhpuhhsrdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghr rghmpehmrghilhhfrhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhmpd hnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehinhht vghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 173EA29C006F; Tue, 4 Mar 2025 13:36:58 -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: Tue, 04 Mar 2025 12:36:37 -0600 To: "php internals" Message-ID: <9964db8c-0ffe-43d5-8246-47fc76b07180@app.fastmail.com> In-Reply-To: References: Subject: Re: [PHP-DEV] PHP True Async RFC Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: larry@garfieldtech.com ("Larry Garfield") On Sat, Mar 1, 2025, at 3:11 AM, Edmond Dantes wrote: > Good day, everyone. I hope you're doing well. > > I=E2=80=99d like to introduce a draft version of the RFC for the True = Async component. > > https://wiki.php.net/rfc/true_async > > I believe this version is not perfect and requires analysis. And I=20 > strongly believe that things like this shouldn't be developed in=20 > isolation. So, if you think any important (or even minor) aspects have=20 > been overlooked, please bring them to attention. > > The draft status also highlights the fact that it includes doubts abou= t=20 > the implementation and criticism. The main global issue I see is the=20 > lack of "future experience" regarding how this API will be used=E2=80=94= another=20 > reason to bring it up for public discussion. > > Wishing you all a great day, and thank you for your feedback! I finally managed to read through enough of the RFC to say something int= elligent. :-) First off, as others have said, thank you for a thorough and detailed pr= oposal. It's clear you've thought through a lot of details. I also esp= ecially like that it's transparent for most IO operations, which is mand= atory for adoption. It's clear to me that async in PHP will never be mo= re than niche until there is a built-in dev-facing API that is easy to u= se on its own without any 3rd party libraries. Unfortunately, at this point I cannot support this proposal, because I d= isagree with the fundamental design primitives. Let's look at the core design primitives: * 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 sta= te 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 functio= ns. The number of ways for this to go wrong and confuse the heck out of a de= veloper is disturbingly high. In the Low-Level API section, the RFC notes: > I came to the conclusion that, in the long run, sacrificing flexibili= ty in favor of code safety is a reasonable trade-off.=20 I completely agree with this statement! And feel the RFC doesn't go eve= n remotely far enough in that direction. In particular, I commend to your attention this post about a Python asyn= c library that very deliberately works at a much higher level of abstrac= tion, and is therefore vastly safer: https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-= considered-harmful/ I won't repeat the post, but suffice to say I agree with it almost entir= ely. (I dislike the name "nursery," but otherwise...) That is the dire= ction we should be looking at for PHP, from the get-go. PHP doesn't have Python-style context managers (though I would like them= ), so a PHP version of that might look something like this (just spitbal= ling): 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 a= sync controls. // If a function doesn't take an AsyncContext param, it cannot control= async. This is good. $context->run(some_function(...)); $result =3D $context->run(function(AsyncContext $ctx) use ($someObj) { // This queues a thunk to run at the end of the closest async {} blo= ck. $ctx->defer($someObj->shutdown(...)); }); } catch (SomeException $e) { // Exception thrown by one of the fibers. } // This is an unwrapped value. print $result; Naturally there would be more to the API, but I'm just showing the basic= s. Importantly: * There is no global modal (schedulerStarted) to think about. * When the async {} block ends, you know with 100% certainty that there = are no dangling background tasks. * It's explicitly obvious what functions are going to try and mess with = the async context, and therefore cannot be called except within an async= context. * An application can have sync portions and async portions very easily, = without worrying about which "mode" it's in at a given time. It also means that writing a number of the utilities mentioned in the RF= C do not require any engine code. Eg: function parallel_map(iterable $it, Closure $fn) { $result =3D []; async $ctx { foreach ($it as $k =3D> $v) { $result[$k] =3D $ctx->run($fn($v)); } } return $result; } Now I know that's safe to call anywhere, whether I'm current in an activ= e async mode or not. =20 I'm not convinced that sticking arbitrary key/value pairs into the Conte= xt object is wise; that's global state by another name. But if we must,= the above would handle all the inheritance and override stuff quite nat= urally. Possibly with: async $ctx from $parentCtx { // ... } Similarly, the two different modes for channels strike me as quite unnec= essary. I also would tend to favor how Rust does channels (via a librar= y, I don't think it's a built-in): have separate variables for the in-si= de and out-side. Again, just spitballing: [$in, $out] =3D Channel::create($buffer_size); $in->send($val); $out->receive($val); (Give or take variations of those methods.) Now you don't need to worry about fibers owning things. You just have a= ChannelIn object and a ChannelOut object, and can pass either one to as= many or as few functions as you want. And those functions could be spa= wning new fibers if you'd like, or not. (There's likely some complicati= ons here I'm not thinking of, but I've not dug into it in depth yet.) Y= ou can now close either side, or just let the objects go out of scope. In short, I am fully in favor of better async logic in PHP. I am very a= gainst an API that even allows me to do something stupid or deadlock-cre= ating, or that relies on hidden global state. That would be worse than = the status quo, and there are better models than what is shown here that= offer much stronger "correct by construction" guarantees. --Larry Garfield