Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:113057 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 22559 invoked from network); 3 Feb 2021 14:44:32 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Feb 2021 14:44:32 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B4E8F1804DC for ; Wed, 3 Feb 2021 06:28:01 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 3 Feb 2021 06:28:01 -0800 (PST) Received: by mail-lj1-f169.google.com with SMTP id e18so28472956lja.12 for ; Wed, 03 Feb 2021 06:28:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=pwioa7W7hECSL3h9G/ChEPTeRFKdclSJWUIMH/AKfjU=; b=b6H7YgQnK/eOJ6o9mh6nGqrlcmCdqwedvNO5WpdKfWLNFSdZubhoxAuxfon0oSWtrP rpV6m58jjkGrFf/avbfHJHZaI2sLLd5+ttT9qQttjjkloBqvaW6phAfPdIz0ilQdP/i1 KYtKVb0AJkOHMzrPdwAD3qYBcvrPBDPSI3boqcGfsNe+W90bMJyGE4t4rzBYunQuOrR4 gyaBS5SXe50KuVglbUa5TAmHeku3BHh7Kepvhgc5w4Dv2rOSyXyFhXQboAcXjCrk+yFG jCLwqUK5fqV+aTtMjHzJPoFC1cCKD/ifqlUBJW5wO8JNLnD2Gav2aFwNzb6EebJgPWpP 8hTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=pwioa7W7hECSL3h9G/ChEPTeRFKdclSJWUIMH/AKfjU=; b=Dz9g+2mmklKvZSlz66e4uBN2+OYjWDZxPmX+BHnYt1riyqUEJj7RGkwnE5d0/0S3+w mj6+2mqWmhin8zccEVNEukaKMgVTtFCxbbeQi9sYO4ntLOoqBQJltYRZs025SRC2V5OQ 6tIhdO+Rs2SgpdIJoQuRZUmjaS0N3YZaP//cVh6aB0zth/Q3nfHVgwsn+R2nG2/z8BaF KfPPkrtqqBiSYhENV1fs8mh7OnZrPeVsNWKaYtqCDXs5uz72Q1a30eUDTT1OWRD1zFnL rQkCUcAycHyquBWGZyH8kB+eSYerYoIQavHSdtfomVP/+ALgvCH0I6CeUIatr+8Wh5wZ gt9Q== X-Gm-Message-State: AOAM5316eA6L4Er5XEcMWMtPwnlo80dyCan81t9dWuq5j3gQw/4Nj3lL Ga7YjNvcsQNlc3YmAHaViln+UmTLScOmTlIKhMk= X-Google-Smtp-Source: ABdhPJziU/GNiu5017R3QwOIyRX3le1cVtUanT1vDWiw9wpPPhIezhabK4WYOil0GymCkfShn9SZsyoFBdGZUtE9wKk= X-Received: by 2002:a05:651c:48c:: with SMTP id s12mr1877500ljc.244.1612362479419; Wed, 03 Feb 2021 06:27:59 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 3 Feb 2021 15:27:43 +0100 Message-ID: To: Niklas Keller Cc: Aaron Piotrowski , php internals Content-Type: multipart/alternative; boundary="000000000000d5c66105ba6f641d" Subject: Re: [PHP-DEV] [RFC] Fibers From: nikita.ppv@gmail.com (Nikita Popov) --000000000000d5c66105ba6f641d Content-Type: text/plain; charset="UTF-8" On Tue, Feb 2, 2021 at 10:35 PM Niklas Keller wrote: > Hey Nikita, > > Thank you for the proposal. Ergonomics of async I/O in PHP certainly leave >> something to be desired right now, and improvements in this area are >> welcome. >> >> Despite your explanations in the RFC and this thread, I'm still having a >> hard time understanding the purpose of the FiberScheduler. >> >> My current understanding is that the FiberScheduler is a special type of >> fiber that cannot be explicitly scheduled by the user -- it is >> automatically scheduled by Fiber::suspend() and automatically un-scheduled >> by Fiber::resume() or Fiber::throw(). It's the fiber that runs between >> fibers :) Does that sound accurate? >> > > Yes, that's accurate. Fibers are used for cooperative multi-tasking and > there's usually a single scheduler responsible for the scheduling. Multiple > schedulers would block each other or busy wait. So having multiple > schedulers is strongly discouraged in long running applications, however, > it might be acceptable in traditional applications, i.e. PHP-FPM. In > PHP-FPM, multiple schedulers partially blocking each other is still better > than blocking entirely for every I/O operation. > > >> What's not clear to me is why the scheduling fiber needs to be >> distinguished from other fibers. If we want to stick with the general >> approach, why is Fiber::suspend($scheduler) not Fiber::transferTo($fiber), >> where $fiber would be the fiber serving as scheduler (but otherwise a >> normal Fiber)? I would expect that context-switching between arbitrary >> fibers would be both most expressive, and make for the smallest interface. >> > > There are a few reasons to make a difference here: > > - SchedulerFibers are run to completion at script end, which isn't the > case for normal fibers. > - Terminating fibers need a fiber to return to. For schedulers it's fine > if a resumed fiber terminates, for normal fibers it should be an exception > if the scheduler fiber terminates without explicitly resuming the suspended > fiber. > - Keeping the previous fiber for each suspension point is complicated if > not impossible to get right and generally complicates the implementation > and cognitive load, see following example: > > main -> A -> B -> C -> A (terminates) -> C (previous) -> B (terminates) -> > C (previous, terminates) -> main > > In the example above, the previous fiber linked list from C back to main > needs to be optimized at some point, otherwise A and B need to be kept in > memory and thus leak memory until C is resumed. > > I'm sure Aaron can present a few other reasons to keep the separation. > Thanks, I didn't consider the terminating fiber case here. But possibly a combination of the two would work? That is, you generally have Fiber::suspend() return to the parent fiber, and make the parent fiber terminating while still having children an error condition. Additionally, you provide something like Fiber::runAsParent() to allow "adopting" a fiber under a new parent, that serves as scheduler (this is to cover the {main} -> scheduler use case). If you stick to the FiberScheduler concept, then you might want to consider inverting the API. Right now you're basically using a standard Fiber API, with the difference that suspend() accepts a FiberScheduler, which is unintuitive to me. If Fibers require a scheduler anyway, why are the suspend and resume methods not on the scheduler? class FiberScheduler { function suspend(Fiber $fiber); function start(Fiber $fiber); function resume(Fiber $fiber); } Both methods are bound to the scheduler in that "suspend" suspends back to a certain scheduler, while "resume" resumes a fiber such that it will return back to this scheduler on termination. This also makes it more obvious that, for example, it's not possible to just do a "$fiber->start()" without having created a scheduler first (though it does not make it obvious that the call has to be from within the scheduler). Regards, Nikita > The more limited alternative is to instead have Fiber::suspend() return to >> the parent fiber (the one that resume()d it). Here, the parent fiber >> effectively becomes the scheduler fiber. If I understand right, the reason >> why you don't want to use that approach, is that it doesn't allow you to >> call some AMP function from the {main} fiber, create the scheduler there >> and then treat {main} just like any other fiber. Is that correct? >> > > Correct, this wouldn't allow top-level Fiber::suspend(). It would also > make the starting / previously resuming party responsible for resuming the > fiber instead of the fiber being able to "choose" the scheduler for a > specific suspension point. One fiber would thus be effectively limited to a > single scheduler. > > Best, > Niklas > --000000000000d5c66105ba6f641d--