Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Deleu
On Fri, Jan 5, 2024 at 9:40 AM Michał Marcin Brzuchalski <
michal.brzuchal...@gmail.com> wrote:

> There are indeed dozens of libraries already working with PSR nicely but
> IMHO
> the API should provide all the necessary information in a way that allows
> the construction of such objects,
> but suggesting PSR with request/response objects will limit the
> capabilities of worker mode API
> to handle pure HTTP protocol only.
>
> What I'd like to say is that I believe for the initial proposal of any
> eventual worker mode API
> with the PSR with request/response objects should not be considered at all.
>
> Cheers
>

I think it's been mentioned quite a few times that it doesn't matter what
gets passed to the callable function that hands over control to userland,
as long as it's more functional-style and not superglobals. I also think
that there's merit in both sides of the conversation between PSR-7 vs
associative arrays, but I find it more important to get one of them, any of
them and not halt for one or the other. PSR would make it HTTP-only, yes,
but that largely benefits the PHP ecosystem to an extent order of magnitude
larger than any non-HTTP format. On the other hand, being a dynamically
typed language, nothing holds us from having a more simple/generic
`function handler(mixed $event)` format which can also be used to process
HTTP and non-HTTP events.

I do prefer the more generic one as I would be interested in seeing what
PHP would become with the capability of processing non-HTTP protocols made
easier. That being said, I find it important to consider the quality of
such an API for its users. It would end up forcing users to do the
following:

```
function handler(mixed $event) {
if (isset($event['_REQUEST'])) {
// We are on HTTP Protocol
}

if (isset($event['...'])) {
// This is a Websocket
}
}
```

If the original proposal is correct and/or my little understanding of this
thread is somewhat in the right direction, it means that the introduction
of a PHP function that asks its engine for the next event to process isn't
a huge amount of work on PHP Internals. If that's true, I would ask that we
consider making something more flexible / forgiving of errors / adjustable
and evolution-friendly. Instead of striving so much for coming up with one
perfect API that shall be the one true API for PHP for the next decade, we
can instead consider the possibility of having multiple small APIs that can
harmonically coexist. Example:

Classic:
```
$classicHttpHandler = function (array $get, array $post, array $request,
array $server, array $cookies): string|Stringable {
// process incoming request in a somewhat backward-compatible friendly
way

return 'http response'; // Return the response similarly to how we used
to `echo` it to the server.
}

worker_http_classic($classicHttpHandler);
```

PSR-7:
```
$httpMiddlewareHandler = function (\Psr\Http\Message\RequestInterface
$request): \Psr\Http\Message\ResponseInterface {
// Process Request
}

worker_http_psr7($httpMiddlewareHandler);
```

HTTP Raw
```
$httpHandler = function (\Psr\Http\Message\StreamInterface $raw):
\Psr\Http\Message\ResponseInterface {
// Process Request
}

worker_http_raw($httpHandler);
```

STDIN
```
$stdinHandler = function (SomeStdinCompatibleType $stdin):
SomeStdoutCompatibleType {

}

worker_stdin($stdinHandler);
```

Websocket
```
$websocketHandler = function (string $event, mixed $data): ??? {
// Process websocket incoming event
}

worker_websocket_event($httpHandler);
```

These APIs don't need to be ready on day one. They don't even need to be
ready at all, actually. Each would end up being its own RFC. What makes the
system a bit more. flexible is the api naming which follows the pattern PHP
Engine Namespace (worker), Purpose Namespace (_http, _websocket, etc) and
Variation Namespace (_classic, _psr7, _raw).

For me personally one awesome last step would make this a PHP Class instead
of procedural functions. That would be even better because we could use the
Class namespace itself to version it and provide future changes without
breaking what's been introduced already.

-- 
Marco Deleu


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Rowan Tommins
On 5 January 2024 12:18:51 GMT, Robert Landers  wrote:
>This is easy to handle from C. If the callback takes an argument,
>don't fill in the super-globals.

Again, that's compatible only in a narrow sense: it provides both APIs on any 
run-time which can do so safely.

You still have an incompatible upgrade to make though: if you write code today 
for FrankenPHP, and directly use the super-global arrays it populates, you 
cannot take that code tomorrow and use it in Swoole, which does not provide 
those super-globals.

If you write code today which uses callback parameters, you can take that code 
and use it unmodified with any system which provides those parameters - 
including async implementations. All that's missing for that to happen right 
now is a standard format for those parameters.


> It allows legacy apps to be slowly
>"upgraded" while allowing newer apps to take full advantage of a SAPI.

It's actually quite easy to add most of the backwards compatibility needed for 
legacy apps in userland, by populating the superglobals, and running an output 
buffer to capture echo etc into the response.


> However, if we go into the design with the
>concurrent server story in mind, I think we can create something much
>better than what is available from FrankenPHP.

Precisely. That's why I used the phrase "forwards compatibility" - I'm not 
saying php-src needs to support all of this right now, just that *the API 
design* should have an eye on the future, not just the past.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Michał Marcin Brzuchalski
pt., 5 sty 2024 o 13:19 Robert Landers 
napisał(a):

> On Fri, Jan 5, 2024 at 11:59 AM Rowan Tommins 
> wrote:
>
> > > Globals is how this works (atm)
> >
> > It's how it works for native SAPIs. It's not, as far as I know, how any
> worker system other than FrankenPHP has implemented its API. Every other
> implementation I've seen, whether async or not, passes in some form of
> request data to the callback, with the exception of RoadRunner, which gives
> the data as a return value from a "get next request" function.
>
> Nearly every library in existence knows how to use these globals
> (including 30 years old legacy code). There are also the unwieldy PSR
> request/response containers for which there are dozens (if not
> hundreds) of implementations. It would be fantastic if there were
> already an extension-based implementation that could be adopted into
> php-src; though I feel like that is a separate conversation.
>

There are indeed dozens of libraries already working with PSR nicely but
IMHO
the API should provide all the necessary information in a way that allows
the construction of such objects,
but suggesting PSR with request/response objects will limit the
capabilities of worker mode API
to handle pure HTTP protocol only.

What I'd like to say is that I believe for the initial proposal of any
eventual worker mode API
with the PSR with request/response objects should not be considered at all.

Cheers


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Robert Landers
On Fri, Jan 5, 2024 at 11:59 AM Rowan Tommins  wrote:
>
> On 5 January 2024 09:02:05 GMT, Robert Landers  
> wrote:
> > I don't think they are fundamentally incompatible. If we look at
> >FrankenPHP's implementation, you pass a callback that gets called when
> >there is a request.
>
> No, you pass a callback which is called exactly once, for the next request. 
> You have to implement your own loop if you want to handle multiple requests, 
> which obviously isn't how it would work with an async event loop.
>
> That was one of my suggested changes: move the loop into C, so that the API 
> was "callback called for each request". This actually *adds* flexibility on 
> the server end, to decide how often to call that callback, do so 
> asynchronously, etc.

I think the goal here is to provide the basic building block: a
function that takes a callable that, when called, blocks the script.
Even when you have an event loop, there is some point when you call
something and enter an infinite loop (the event loop), and no more of
that file will be called ($app->start() or whatever). This is _that
function_ for all intents and purposes. You can implement your own
event-loop using do/while (such as in FrankenPHP), or a SAPI can call
it in a loop for you. The bedrock is in core PHP, providing a
standardized way of setting this up ... obviously, there are also
SAPIs out there doing their own thing, and there always will be.

> > Globals is how this works (atm)
>
> It's how it works for native SAPIs. It's not, as far as I know, how any 
> worker system other than FrankenPHP has implemented its API. Every other 
> implementation I've seen, whether async or not, passes in some form of 
> request data to the callback, with the exception of RoadRunner, which gives 
> the data as a return value from a "get next request" function.

Nearly every library in existence knows how to use these globals
(including 30 years old legacy code). There are also the unwieldy PSR
request/response containers for which there are dozens (if not
hundreds) of implementations. It would be fantastic if there were
already an extension-based implementation that could be adopted into
php-src; though I feel like that is a separate conversation.

> So, the second suggested change is to standardise on the most common pattern 
> of passing parameters to a callback, rather than the unusual one of 
> populating and clearing superglobals. As a bonus, this pattern works with 
> both non-async and async workers.
>
>
> > changing the signature of the callback is generally backwards compatible
>
> This is true in the narrow sense that it won't cause any fatal errors. But if 
> you write your application assuming that it will run in an environment where 
> globals are populated for you, it will not run in an environment which no 
> longer populates those globals.

This is easy to handle from C. If the callback takes an argument,
don't fill in the super-globals. It allows legacy apps to be slowly
"upgraded" while allowing newer apps to take full advantage of a SAPI.
That's how I would implement it, anyway. There is also something to be
said to go "all the way" and just abandoning legacy apps, but that
doesn't feel like something PHP would do.

> >Changing the underlying implementation in php-src when there are
> >native fibers/event loops probably won't even change anything (since
> >that was exactly how they were designed).
>
> Sounds great! So we don't need to wait to put that implementation in place 
> then.
>
>
>
> >But holding up the entire conversation ...
>
> There is no reason whatsoever to hold anything up. The suggestion is not 
> "don't implement any worker API until we have an async implementation", it's 
> "a worker API sounds great, let's implement one that looks like this".
>
> Yes, it might take slightly longer to define some new array structures, but 
> we're talking about a few hours work to give us a much more flexible system, 
> not weeks of complex engineering.
>
> If the proposal is "copy some code from FrankenPHP into php-src, which nobody 
> else will want to use", it's pointless; if it's "standardise an API with some 
> enabling code", then *of course* we want to spend a bit of time designing 
> that API.

That's fair. I was taking this push-back from you and others as, "No,
we don't want this unless we can have all these other things," so
thank you for clarifying that. I can largely agree -- I use amphp +
fibers extensively in another project, so seeing more love for
concurrent servers would be nice. Maybe I saw it that way because I
have a fairly deep understanding of the shortcomings with
fibers/async-php and see the amount of work required to support what
you are proposing. However, if we go into the design with the
concurrent server story in mind, I think we can create something much
better than what is available from FrankenPHP.

> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> 

Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Rowan Tommins
On 5 January 2024 09:02:05 GMT, Robert Landers  wrote:
> I don't think they are fundamentally incompatible. If we look at
>FrankenPHP's implementation, you pass a callback that gets called when
>there is a request.

No, you pass a callback which is called exactly once, for the next request. You 
have to implement your own loop if you want to handle multiple requests, which 
obviously isn't how it would work with an async event loop.

That was one of my suggested changes: move the loop into C, so that the API was 
"callback called for each request". This actually *adds* flexibility on the 
server end, to decide how often to call that callback, do so asynchronously, 
etc.



> Globals is how this works (atm)

It's how it works for native SAPIs. It's not, as far as I know, how any worker 
system other than FrankenPHP has implemented its API. Every other 
implementation I've seen, whether async or not, passes in some form of request 
data to the callback, with the exception of RoadRunner, which gives the data as 
a return value from a "get next request" function.

So, the second suggested change is to standardise on the most common pattern of 
passing parameters to a callback, rather than the unusual one of populating and 
clearing superglobals. As a bonus, this pattern works with both non-async and 
async workers.


> changing the signature of the callback is generally backwards compatible

This is true in the narrow sense that it won't cause any fatal errors. But if 
you write your application assuming that it will run in an environment where 
globals are populated for you, it will not run in an environment which no 
longer populates those globals.



>Changing the underlying implementation in php-src when there are
>native fibers/event loops probably won't even change anything (since
>that was exactly how they were designed).

Sounds great! So we don't need to wait to put that implementation in place then.



>But holding up the entire conversation ...

There is no reason whatsoever to hold anything up. The suggestion is not "don't 
implement any worker API until we have an async implementation", it's "a worker 
API sounds great, let's implement one that looks like this".

Yes, it might take slightly longer to define some new array structures, but 
we're talking about a few hours work to give us a much more flexible system, 
not weeks of complex engineering.

If the proposal is "copy some code from FrankenPHP into php-src, which nobody 
else will want to use", it's pointless; if it's "standardise an API with some 
enabling code", then *of course* we want to spend a bit of time designing that 
API.


Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Daniil Gentili
Hi,

> But holding up the entire conversation because these things don't even
> exist,

BTW, I'm not asking to wait for the implementation of a native event loop 
before implementing a worker mode, I'm asking to design the worker mode API in 
a way that is compatible with an eventual native event loop (that I hope will 
eventually get merged into php, as the current status quo of blocking STL I/O 
is definitely not ideal for a programming language in 2024).

Using superglobals for request information is already using a wrong approach in 
sight of native async, and while technically this is not completely 
incompatible with fibers, as superglobals can simply be copied immediately as 
soon a fiber is started, the same cannot be said for php://output and 
php://input streams, which cannot be copied in any way.

I ask to completely avoid altering superglobals and other global state such as 
the php://input/output streams, and instead directly pass/return an 
array/object (it really does not matter to me if it's a PSR-7 RequestInterface 
or an array containing _GET, _POST, input, output keys, or anything else as 
long as superglobals and global state is not touched in any way).

Backwards compatibility for code using superglobals is really a non-issue here, 
as worker mode in itself is already potentially NOT automatically 
backwards-compatible with legacy code, since applications running in worler 
mode have to deal with the fact that the global state is not reset at the end 
of each request.

This in itself is not an issue as mentioned before, thanks to work inside of 
major PHP frameworks to better support worker mode, I.e. laravel octane, but 
since the beneficiaries of worker mode will mostly be modern frameworks and 
most legacy code will already require changes to better support it, using a new 
API with a standalone request object/array instead of superglobals is not a 
real issue.

Regards,
Daniil Gentili.


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-05 Thread Robert Landers
On Fri, Jan 5, 2024 at 8:47 AM Rowan Tommins  wrote:
>
> On 5 January 2024 06:55:34 GMT, Robert Landers  
> wrote:
>
> >I already said this, but to reiterate: I, personally, hear what you
> >are saying and largely agree with you; however, before we can really
> >have any kind of discussion on concurrent servers, we HAVE to address
> >the underlying issues that are missing from PHP. In PHP-src
>
> So, let's address them...
>
>
> > there are no such things as request objects
>
> This is a non-issue. As has been discussed already, it's perfectly fine to 
> have an event-based system where the event details are an associative array, 
> rather than a rich object.
>
>
>
> > There are no such things as event loops. There are fibers,
> > but absolutely no std-library i/o functions are using them
>
> This is what the bulk of Daniil's email is suggesting a way to improve.
>
>
> >We have a long way to go before those will be real things that we can
> >have a proper conversation about in the context of php-src.
>
> If we keep waiting to have the conversation, it will never happen.
>
> And if we start building brand new APIs like infrastructure for worker-mode 
> SAPIs, in ways that are fundamentally incompatible with async, we're just 
> making more work for ourselves when we do get there.

I don't think they are fundamentally incompatible. If we look at
FrankenPHP's implementation, you pass a callback that gets called when
there is a request. This is the same as giving Swoole a callback to
call when a request is received, though the underlying implementation
might be very different. An event-loop doesn't matter here and what
gets passed to the callback is what we are discussing here.

The exact implementation (in php-src) matters, but only so far as what
php-src is capable of. Globals is how this works (atm) and changing
the signature of the callback is generally backwards compatible. For
example, if we start with only globals (no parameters), adding
parameters later once there are request objects/arrays/whatever, is
fine. Calling a callback with parameters when the function actually
doesn't accept any arguments, isn't even a notice
(https://3v4l.org/URj9b).

Changing the underlying implementation in php-src when there are
native fibers/event loops probably won't even change anything (since
that was exactly how they were designed).

But holding up the entire conversation because these things don't even
exist, seems like a pointless endeavor since they may not even pass
the RFC point (IIRC, getting an event-loop in PHP was a large part of
the reason fibers are the way they are because people were against an
event-loop at that time).

> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>


Robert Landers
Software Engineer
Utrecht NL

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-04 Thread Rowan Tommins
On 5 January 2024 06:55:34 GMT, Robert Landers  wrote:

>I already said this, but to reiterate: I, personally, hear what you
>are saying and largely agree with you; however, before we can really
>have any kind of discussion on concurrent servers, we HAVE to address
>the underlying issues that are missing from PHP. In PHP-src

So, let's address them...


> there are no such things as request objects

This is a non-issue. As has been discussed already, it's perfectly fine to have 
an event-based system where the event details are an associative array, rather 
than a rich object.



> There are no such things as event loops. There are fibers,
> but absolutely no std-library i/o functions are using them

This is what the bulk of Daniil's email is suggesting a way to improve.


>We have a long way to go before those will be real things that we can
>have a proper conversation about in the context of php-src.

If we keep waiting to have the conversation, it will never happen. 

And if we start building brand new APIs like infrastructure for worker-mode 
SAPIs, in ways that are fundamentally incompatible with async, we're just 
making more work for ourselves when we do get there.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-04 Thread Robert Landers
On Fri, Jan 5, 2024 at 2:56 AM Daniil Gentili  wrote:
>
> Hi,
>
> I've been lurking around in the discussion for a while, and I'd like to chime 
> in now since the main, glaring issue with this proposal has only been 
> explicitly mentioned by Rowan Tomminis, with that subthread quickly 
> degenerating with misguided replies.
>
> PHP as a language absolutely needs a persistent worker mode like in all other 
> backend languages, which will greatly improve performance by avoiding all 
> overhead related to request initialization.
>
> However, the current proposal of adding support for worker mode SAPIs based 
> on the usual PHP superglobals is fundamentally incompatible with concurrency 
> (aka async, aka swoole, amphp, fiber-based concurrent runtimes in general), 
> and I believe would steer the PHP ecosystem in the wrong direction.
>
> Rowan already offered a nice example of why earlier in the thread, but as an 
> explanation to those that may not have understood that, so I whipped up a 
> briefer at https://gist.github.com/danog/f0e9103e6a7e1bcec1b92c411a3c4607
>
>
>
> So no, unlike what I've read in another message here, "The nodejs curse [...] 
> where async and co may actually slow down your whole node." is simply false 
> for the majority of modern usecases, because the majority of modern 
> applications is I/O-intensive, not CPU-intensive.
>
>
> Implementing a worker API the way it is proposed is fundamentally 
> incompatible with userland cooperative schedulers aka event loops like amphp 
> or reactphp, and each request would be handled, just like in php-fpm, in a 
> separate OS thread, not in a much more efficient userland thread.
>
> Cooperative schedulers implemented outside of PHP in the form of an extension 
> such as swoole would also not be able to easily make use of the initially 
> proposed API to handle requests in separate coroutines, even if the 
> handle_request function was intercepted by swoole to return control to the 
> swoole event loop (which would already make it superfluous as a PHP API), 
> since the proposal involves messing around with the usual superglobals, which 
> as mentioned by Rowan would require manual copying of the superglobals before 
> using them in a newly spawned swoole coroutine.
>
> I believe that a much, much better way of implementing a worker mode in PHP 
> core would be to provide a fiber-aware function/static method returning, upon 
> receiving a request, a class implementing the PSR-7 RequestInterface.
>
> Fiber-aware here means that the function should behave in a way similar to 
> how all native PHP I/O functions should behave in an upcoming Native Event 
> Loop RFC I'm planning to make.
>
> The idea here is to make all I/O related functions, including this new 
> wait_request function, completely async in a manner that is compatible with 
> fibers and pure PHP event loops like amphp.
>
> It would essentially work as follows: an event loop like uv is integrated 
> within PHP itself at least for the native stream wrapper (I.e. all filesystem 
> and network functions, file_get_contents and so on).
> Extensions will be provided an API to interact with the event loop.
>
> I'm currently finalizing the details, and might probably make a first RFC in 
> the coming weeks, suffice to say that everything will work in a manner very 
> similar to how async works in both the ext-pq and php-tokio extensions, 
> albeit with fiber integration: a separate event loop (let's call it native) 
> is started in another OS thread (like with ext-pq or php-tokio, WITHOUT the 
> need for ZTS, as no PHP data structures are modified in the native event 
> loop), events are sent via a single descriptor from the native event loop to 
> the userland event loop (I.e. amphp).
>
> If running inside a fiber, tasks are queued to the native event loop and the 
> fiber is suspended with a NativeSuspension, then resumed by the userland 
> event loop.
>
> If not running inside a fiber, tasks are queued to the native event loop and 
> control is returned to the userland event loop.
>
> Essentially, my proposal is almost exactly what is already being done in 
> https://github.com/danog/php-tokio, but library-agonstic and implemented 
> inside of PHP itself, perhaps even using Rust and tokio as well.
>
> I feel that the current direction of the discussion of PHP worker modes is 
> wrong, as it is mostly ignoring the presence of a perfectly usable 
> concurrency API in PHP (fibers): this has potential to cause a big split in 
> the PHP ecosystem, unless PHP finally fully embraces concurrency and async 
> with a native event loop proposal, like the one I intend to present soon.
>
> I hope that further discussion of a worker mode continues with an eye to the 
> future with native concurrency :)
>
> Regards,
> Daniil Gentili.
>
> P. S. Just in case to avoid confusion for some, frankenphp does NOT add 
> native concurrency to php using goroutines, as control to the go event loop 
> is only returned 

Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-04 Thread Daniil Gentili
Hi,

I've been lurking around in the discussion for a while, and I'd like to chime 
in now since the main, glaring issue with this proposal has only been 
explicitly mentioned by Rowan Tomminis, with that subthread quickly 
degenerating with misguided replies.

PHP as a language absolutely needs a persistent worker mode like in all other 
backend languages, which will greatly improve performance by avoiding all 
overhead related to request initialization.

However, the current proposal of adding support for worker mode SAPIs based on 
the usual PHP superglobals is fundamentally incompatible with concurrency (aka 
async, aka swoole, amphp, fiber-based concurrent runtimes in general), and I 
believe would steer the PHP ecosystem in the wrong direction.

Rowan already offered a nice example of why earlier in the thread, but as an 
explanation to those that may not have understood that, so I whipped up a 
briefer at https://gist.github.com/danog/f0e9103e6a7e1bcec1b92c411a3c4607



So no, unlike what I've read in another message here, "The nodejs curse [...] 
where async and co may actually slow down your whole node." is simply false for 
the majority of modern usecases, because the majority of modern applications is 
I/O-intensive, not CPU-intensive.


Implementing a worker API the way it is proposed is fundamentally incompatible 
with userland cooperative schedulers aka event loops like amphp or reactphp, 
and each request would be handled, just like in php-fpm, in a separate OS 
thread, not in a much more efficient userland thread.

Cooperative schedulers implemented outside of PHP in the form of an extension 
such as swoole would also not be able to easily make use of the initially 
proposed API to handle requests in separate coroutines, even if the 
handle_request function was intercepted by swoole to return control to the 
swoole event loop (which would already make it superfluous as a PHP API), since 
the proposal involves messing around with the usual superglobals, which as 
mentioned by Rowan would require manual copying of the superglobals before 
using them in a newly spawned swoole coroutine.

I believe that a much, much better way of implementing a worker mode in PHP 
core would be to provide a fiber-aware function/static method returning, upon 
receiving a request, a class implementing the PSR-7 RequestInterface.

Fiber-aware here means that the function should behave in a way similar to how 
all native PHP I/O functions should behave in an upcoming Native Event Loop RFC 
I'm planning to make.

The idea here is to make all I/O related functions, including this new 
wait_request function, completely async in a manner that is compatible with 
fibers and pure PHP event loops like amphp.

It would essentially work as follows: an event loop like uv is integrated 
within PHP itself at least for the native stream wrapper (I.e. all filesystem 
and network functions, file_get_contents and so on).
Extensions will be provided an API to interact with the event loop.

I'm currently finalizing the details, and might probably make a first RFC in 
the coming weeks, suffice to say that everything will work in a manner very 
similar to how async works in both the ext-pq and php-tokio extensions, albeit 
with fiber integration: a separate event loop (let's call it native) is started 
in another OS thread (like with ext-pq or php-tokio, WITHOUT the need for ZTS, 
as no PHP data structures are modified in the native event loop), events are 
sent via a single descriptor from the native event loop to the userland event 
loop (I.e. amphp).

If running inside a fiber, tasks are queued to the native event loop and the 
fiber is suspended with a NativeSuspension, then resumed by the userland event 
loop.

If not running inside a fiber, tasks are queued to the native event loop and 
control is returned to the userland event loop.

Essentially, my proposal is almost exactly what is already being done in 
https://github.com/danog/php-tokio, but library-agonstic and implemented inside 
of PHP itself, perhaps even using Rust and tokio as well.

I feel that the current direction of the discussion of PHP worker modes is 
wrong, as it is mostly ignoring the presence of a perfectly usable concurrency 
API in PHP (fibers): this has potential to cause a big split in the PHP 
ecosystem, unless PHP finally fully embraces concurrency and async with a 
native event loop proposal, like the one I intend to present soon.

I hope that further discussion of a worker mode continues with an eye to the 
future with native concurrency :)

Regards,
Daniil Gentili.

P. S. Just in case to avoid confusion for some, frankenphp does NOT add native 
concurrency to php using goroutines, as control to the go event loop is only 
returned when calling functions like header or echo which cause a suspension of 
the goroutine because an I/O operation is made on the go side, but

1) That's incompatible with fibers, and not just because of the minor go 

Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-02 Thread Jakub Zelenka
On Tue, Jan 2, 2024 at 3:46 PM Jeffrey Dafoe  wrote:

> > > Again, the representation as objects isn't a key requirement. Python's
> > > WSGI spec simply has a dictionary (read: associative array) of the
> > > environment based on CGI. The application might well turn that into a
> > > more powerful object, but standardisation of such wasn't considered a
> > > pre-requisite, and would actually have hampered ASGI, where not all
> > > events represent an HTTP request.
>
> Jumping in to add that NGINX has their newish Unit app server, which uses
> Yet Another Custom SAPI for PHP.
>
>
It seems to me that its development significantly decreased after F5
takeover and the unit main developer leaving the company so not sure if
there is that much future in it.

Cheers

Jakub


RE: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-02 Thread Jeffrey Dafoe
> > Again, the representation as objects isn't a key requirement. Python's
> > WSGI spec simply has a dictionary (read: associative array) of the
> > environment based on CGI. The application might well turn that into a
> > more powerful object, but standardisation of such wasn't considered a
> > pre-requisite, and would actually have hampered ASGI, where not all
> > events represent an HTTP request.

Jumping in to add that NGINX has their newish Unit app server, which uses Yet 
Another Custom SAPI for PHP.

-Jeff

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-01 Thread Rowan Tommins
I'm running out of different ways to say the same thing, and not really 
sure which part of my previous messages people haven't understood. I'm 
really not saying anything very controversial or complicated, just "had 
you considered that style B would offer these additional possibilities 
over style A".


So I'm going to quote the parts of previous messages which I think 
already answer the latest questions.


After that, I'm going to leave the thread to others for a bit, unless I 
see a question that isn't just retreading the same ground.




On 01/01/2024 17:36, Pierre Joye wrote:
Unless I misunderstand the current proposal, it is about providing a 
core interface to allow one to create its own SAPI similar to 
FrankenPHP, which does not handle request in a singe thread but a 
thread pool handled by go's coroutine.



From Kévin's opening post:


In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
engines supporting worker modes.

[...]

the existence of a common infrastructure would standardize the way worker
scripts are created and provide a high-level PHP API for writing worker
scripts that work with all SAPIs that rely on this new feature.


From my last message:


If we're attempting to standardise a new API for worker modes (i.e. HTTP servers which 
are no longer "shared nothing"), choosing one which can be used by consecutive 
worker modes (FrankenPHP , RoadRunner) but not concurrent ones (Swoole, ReactPHP, AMPHP) 
feels like a big missed opportunity.




On 01/01/2024 17:40, Robert Landers wrote:

I'm not sure concurrent servers would even be able to be in scope if
we wanted them to be?


From my message dated 2023-12-29 22:55 UTC:

Note that both async and WebSockets were mentioned as possible 
"forward compatibility". If we're talking about "next generation 
SAPIs", these are the kinds of features that people will be - and 
already are - developing; so it seems foolish not to at least consider 
them when designing new baseline APIs.



On 01/01/2024 17:36, Pierre Joye wrote:

It is a first step and based on the usages/feedback, the next steps 
could be the second part of your comment. Or?


From my message dated 2023-12-31 01:20 UTC:


if you standardise on an API that populates global state, you close off any 
possibility of using that API in a concurrent environment. If you instead 
standardise on callbacks which hold request and response information in their 
own scope, you don't close anything off.


And from 2023-12-30 10:53 UTC:


The key requirement is that you have some way of passing the current request 
and response around as scoped variables, not global state. That's essential for 
any kind of concurrent run-time (async, thread-aware, etc).



Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-01 Thread Robert Landers
On Mon, Jan 1, 2024 at 12:18 PM Rowan Tommins  wrote:
>
> On 31 December 2023 16:31:31 GMT, Pierre Joye  wrote:
>
> >php handles this in threadsafe mode
>
> Depending on your exact definition of "php", this is either irrelevant or 
> just plain wrong.
>
> If you mean "the HTTP SAPIs shipped with official builds of PHP", then it's 
> true, none handle multiple concurrent requests in a single thread using async 
> I/O. But none handle multiple consecutive requests in a single thread using a 
> "worker mode" either, which is the whole point of this conversation.
>
> If you mean for "php" to include third party HTTP handlers such as 
> FrankenPHP, then it also includes Swoole, which is what I was describing. 
> Please someone correct me if I'm wrong, but I understand ReactPHP and AMPHP 
> also include HTTP servers using the same principle.
>
> So, to reiterate my point once more: implementations of PHP using async 
> concurrency are out there already in production use. If we're attempting to 
> standardise a new API for worker modes (i.e. HTTP servers which are no longer 
> "shared nothing"), choosing one which can be used by consecutive worker modes 
> (FrankenPHP , RoadRunner) but not concurrent ones (Swoole, ReactPHP, AMPHP) 
> feels like a big missed opportunity.
>
> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

Hey Rowan,

I'm not sure concurrent servers would even be able to be in scope if
we wanted them to be? PHP doesn't have an "event-loop", concurrent
i/o, or any building blocks needed to serve concurrent requests. It's
been made possible through extensions and libraries that aren't
maintained by PHP, so I'm not sure how we'd support them directly
without those other basic functionalities. If we directly wanted to
support concurrent servers, I think there is probably a lot of work to
do at a very low level before we could realistically include them in
this part of the conversation.




Robert Landers
Software Engineer
Utrecht NL

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-01 Thread Pierre Joye
On Mon, Jan 1, 2024, 6:18 PM Rowan Tommins  wrote:

> On 31 December 2023 16:31:31 GMT, Pierre Joye 
> wrote:
>
> >php handles this in threadsafe mode
>
> Depending on your exact definition of "php", this is either irrelevant or
> just plain wrong.
>
> If you mean "the HTTP SAPIs shipped with official builds of PHP", then
> it's true, none handle multiple concurrent requests in a single thread
> using async I/O. But none handle multiple consecutive requests in a single
> thread using a "worker mode" either, which is the whole point of this
> conversation.
>


Unless I misunderstand the current proposal, it is about providing a core
interface to allow one to create its own SAPI similar to FrankenPHP, which
does not handle request in a singe thread but a thread pool handled by go's
coroutine.

I can imagine other developers implement it using other mechanisms (rust or
c++ f.e.) but the main interface from a php internal pov remains.

It is a first step and based on the usages/feedback, the next steps could
be the second part of your comment. Or?

best,
Pierre

>


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2024-01-01 Thread Rowan Tommins
On 31 December 2023 16:31:31 GMT, Pierre Joye  wrote:

>php handles this in threadsafe mode

Depending on your exact definition of "php", this is either irrelevant or just 
plain wrong.

If you mean "the HTTP SAPIs shipped with official builds of PHP", then it's 
true, none handle multiple concurrent requests in a single thread using async 
I/O. But none handle multiple consecutive requests in a single thread using a 
"worker mode" either, which is the whole point of this conversation.

If you mean for "php" to include third party HTTP handlers such as FrankenPHP, 
then it also includes Swoole, which is what I was describing. Please someone 
correct me if I'm wrong, but I understand ReactPHP and AMPHP also include HTTP 
servers using the same principle.

So, to reiterate my point once more: implementations of PHP using async 
concurrency are out there already in production use. If we're attempting to 
standardise a new API for worker modes (i.e. HTTP servers which are no longer 
"shared nothing"), choosing one which can be used by consecutive worker modes 
(FrankenPHP , RoadRunner) but not concurrent ones (Swoole, ReactPHP, AMPHP) 
feels like a big missed opportunity.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-31 Thread Pierre Joye
hello,

On Sun, Dec 31, 2023, 6:59 PM Rowan Tommins  wrote:

Then one of us is missing something very fundamental. As I understand it,
> Swoole's model is similar to that popularised by node.js: a single thread
> processes multiple incoming requests concurrently, using asynchronous I/O.


The nodejs curse yes, where async and co may actually slow down your whole
node.

 DB result
> 09 Request A formats and returns response
> 10 Request A complete
> 11 Request B resumed
> 12 Request B fornats and returns response
>

php handles this in threadsafe mode, like modphp f.e. It is why frankenphp
requires a TS build of php. Requests are handled by a thread pool, not in
single thread event loop which may block all requests.

best,
Pierre


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-31 Thread Rowan Tommins
On 31 December 2023 08:31:16 GMT, "Kévin Dunglas"  wrote:
>This new function is intended for SAPIs. Swoole was given as an example of
>worker mode, but it isn't a SAPI. AFAIK, it doesn't use the SAPI
>infrastructure provided by PHP.
>The scope of my proposal is only to provide a new feature in the SAPI
>infrastructure to build worker modes to handle HTTP requests, not to deal
>with non-SAPI engines.

One of the advantages you suggested of your proposal is that users would have a 
consistent way to write worker scripts. To achieve that, you want a *design* 
that can be adopted by as many implementations as possible, regardless of how 
they implement it. Providing helper infrastructure for that design is a 
secondary concern - as you admit, the actual code you're proposing to add is 
quite short.


>That being said, I don't understand what would prevent Swoole from
>implementing the proposed API

Then one of us is missing something very fundamental. As I understand it, 
Swoole's model is similar to that popularised by node.js: a single thread 
processes multiple incoming requests concurrently, using asynchronous I/O. For 
instance, a thread might run the following:

01 Request A received
02 Request A input validated
03 Request A sends async query to DB
04 Request A hands control to event loop while it awaits result
05 Request B received
06 Request B sends async HTTP call to some API
07 Request B awaits result
08 Request A resumed with DB result
09 Request A formats and returns response
10 Request A complete
11 Request B resumed
12 Request B fornats and returns response

Each request has its own call stack, started by a different call to the 
registered event handler, but any global state is shared between them - there 
is no actual threading going on, so no partitioned memory.

If requests are communicated by setting up superglobals, that will happen at 
step 01 and again at step 05. If you try to read from them at step 09, you 
would see them populated with information about request B, but you're trying to 
handle request A.

It would be possible to work around that by placing large warnings to users not 
to read superglobals after any async call - basically forcing them to create 
scoped copies to pass around. But the worse problem is output: if step 09 and 
step 12 both just use "echo", how do you track which output needs to go to 
which network connection? You can't just set up an output buffer, because 
that's global state shared by both call stacks. You have to put *something* 
into the scope of the call stack - a callback to write output, an expected 
return value, etc.

Asynchronous code ends up somewhat resembling functional programming: 
everything you want to have side effects on needs to be passed around as 
parameters and return values, because the only thing isolated between requests 
is local variable scope.
 
Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-31 Thread Kévin Dunglas
On Sun, Dec 31, 2023 at 2:20 AM Rowan Tommins 
wrote:

> On 30 December 2023 19:48:39 GMT, Larry Garfield 
> wrote:
> >The Franken-model is closer to how PHP-FPM works today, which means that
> is easier to port existing code to, especially existing code that has lots
> of globals or hidden globals.  (Eg, Laravel.)  That may or may not make it
> the better model overall, I don't know, but it's the more-similar model.
>
> That's why I said earlier that it provides better backwards compatibility
> - existing code which directly uses PHP's current global state can more
> easily be run in a worker which populates that global state.
>
> However, the benefit is marginal, for two reasons. Firstly, because in
> practice a lot of applications avoid touching the global state outside of
> some request bootstrapping code anyway. The FrankenPHP example code and
> Laravel Octane both demonstrate this.
>
> Secondly, because in an environment that handles a single request at a
> time, the reverse is also possible: if the server passes request
> information directly to a callback, that callback can populate the
> superglobals as appropriate. The only caveat I can think of is input
> streams, since userland code can't reset and populate php://input, or
> repoint STDOUT.
>
> On the other hand, as soon as you have any form of concurrency, the two
> models are not interchangeable - it would make no sense for an asynchronous
> callback to read from or write to global state.
>
> And that's what I meant about FrankenPHP's API having poor forward
> compatibility - if you standardise on an API that populates global state,
> you close off any possibility of using that API in a concurrent
> environment. If you instead standardise on callbacks which hold request and
> response information in their own scope, you don't close anything off.
>
> If anything, calling this "forwards compatibility" is overly generous: the
> OP gave Swoole as an example of an existing worker environment, but I can't
> see any way that Swoole could implement an API that communicated request
> and response information via global state.
>
> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php


This new function is intended for SAPIs. Swoole was given as an example of
worker mode, but it isn't a SAPI. AFAIK, it doesn't use the SAPI
infrastructure provided by PHP.
The scope of my proposal is only to provide a new feature in the SAPI
infrastructure to build worker modes to handle HTTP requests, not to deal
with non-SAPI engines.
That being said, I don't understand what would prevent Swoole from
implementing the proposed API, or even to implement a userland
implementation of the proposed API using Swoole under the hood.
It seems doable to emulate the sequential request handling and to create an
adapter from their custom objects to superglobals and streams.

For WebSockets and WebTransports, the same considerations apply. The SAPI
API will have to be extended to deal with such low-level network layers,
worker mode or not. To me, this is very interesting (and needed) but should
be discussed in another RFC.

As pointed out by Crell, FrankenPHP (and similar theoretical solutions)
starts as many workers as needed. This can be a fixed set of workers, as in
FrankenPHP, or a dynamic number of workers, similar to traditional FPM
workers.

FrankenPHP uses threads to parallelize request handling (to start several
instances of the worker script in parallel). Other techniques could be
used, for instance, in the future, we could use goroutines (which use a mix
of system threads and async IO, and goroutines are handled in a single
system thread:
https://github.com/golang/go/blob/master/src/runtime/HACKING.md#gs-ms-ps)
instead of threads, by adding a new backend to TSRM.

The global state is never reset in the same worker context, it is preserved
across requests, except for superglobals and streams, which are updated
with the data of the request being handled.

Superglobals are the PHP way to expose CGI-like data. Adding support for
other ways to do it such as proposed by WSGI, and/or new objects and the
like could be interesting, but again this isn't the scope of this proposal
which is narrow, and tries to reuse the existing infrastructure as much as
possible. The proposal is simple enough to support new ways if introduced
at some point in PHP, and the Symfony Runtime and Laravel Octane libraries
prove that it's possible to implement more advanced data structures
user-land on top of the existing superglobals infrastructure.

Regarding the infinite loop, we could indeed remove it using a few lines of
code. I hesitated to do that initially, but the loop gives more flexibility
by allowing the implementation of many features in user-land (like
restarting the worker after a fixed number of requests, when the memory
reaches a certain level, etc). Without this loop, all these 

Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Rowan Tommins
On 30 December 2023 19:48:39 GMT, Larry Garfield  wrote:
>The Franken-model is closer to how PHP-FPM works today, which means that is 
>easier to port existing code to, especially existing code that has lots of 
>globals or hidden globals.  (Eg, Laravel.)  That may or may not make it the 
>better model overall, I don't know, but it's the more-similar model.

That's why I said earlier that it provides better backwards compatibility - 
existing code which directly uses PHP's current global state can more easily be 
run in a worker which populates that global state.

However, the benefit is marginal, for two reasons. Firstly, because in practice 
a lot of applications avoid touching the global state outside of some request 
bootstrapping code anyway. The FrankenPHP example code and Laravel Octane both 
demonstrate this.

Secondly, because in an environment that handles a single request at a time, 
the reverse is also possible: if the server passes request information directly 
to a callback, that callback can populate the superglobals as appropriate. The 
only caveat I can think of is input streams, since userland code can't reset 
and populate php://input, or repoint STDOUT.

On the other hand, as soon as you have any form of concurrency, the two models 
are not interchangeable - it would make no sense for an asynchronous callback 
to read from or write to global state.

And that's what I meant about FrankenPHP's API having poor forward 
compatibility - if you standardise on an API that populates global state, you 
close off any possibility of using that API in a concurrent environment. If you 
instead standardise on callbacks which hold request and response information in 
their own scope, you don't close anything off.

If anything, calling this "forwards compatibility" is overly generous: the OP 
gave Swoole as an example of an existing worker environment, but I can't see 
any way that Swoole could implement an API that communicated request and 
response information via global state.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Michał Marcin Brzuchalski
Hi Larry,

sob., 30 gru 2023 o 20:49 Larry Garfield 
napisał(a):

> On Sat, Dec 30, 2023, at 4:53 AM, Rowan Tommins wrote:
> > On 30 December 2023 09:59:07 GMT, Robert Landers
> >  wrote:
> >>For this to happen in PHP Core, there would need to be request objects
> >>instead of a global state.
> >
> > Again, the representation as objects isn't a key requirement. Python's
> > WSGI spec simply has a dictionary (read: associative array) of the
> > environment based on CGI. The application might well turn that into a
> > more powerful object, but standardisation of such wasn't considered a
> > pre-requisite, and would actually have hampered ASGI, where not all
> > events represent an HTTP request.
> >
> > The key requirement is that you have some way of passing the current
> > request and response around as scoped variables, not global state.
> > That's essential for any kind of concurrent run-time (async,
> > thread-aware, etc).
> >
> > An event / subscriber model fits well with that: the local scope for
> > each request is set up by an invocation of the callback with defined
> > parameters and return value.
> >
> > Funnily enough, the example of a worker script for FrankenPHP does both
> > things: it sends each request to the same application "handle"
> > callback, passing in the super-global arrays as parameters to be used
> > as non-global state. https://frankenphp.dev/docs/worker/#custom-apps So
> > really all I'm arguing is that a few more lines of that PHP example be
> > moved into the C implementation, so that the user only needs to provide
> > that inner callable, not the outer while loop.
>
> So you're suggesting something like:
>
> $app->initializeStuffHowever();
> set_event_handler(Closure $handler);
> // Script blocks here until a sigkill is received, or something.
>
> I think there's an important distinction that is getting missed in the
> above discussion, beyond the push-vs-pull question.  FrankenPHP, as I
> understand it, pre-boots multiple worker processes, keeps them in memory,
> and then handles each request in its own process.  Swoole,
> Amp/React/Revolt, and friends have only a single process running at all,
> and make use of async to simulate multiple simultaneous requests, a la
> NodeJs.  That means mutable global variables in the FrankenPHP model still
> won't leak between parallel requests, whereas they absolutely would/do in a
> Swole/Revolt world.
>
> I'm not going to call one of those better or worse (I don't have enough
> experience with either to say), but they are different beasts for which
> first class support would be different SAPIs either way.  They're not
> mutually exclusive thanks to Fibers (which mean you don't need the entire
> call stack to be async), but you would want to pick one or the other as
> primary runner mode of an application.  Let's keep that in mind when making
> comparisons.
>
> The Franken-model is closer to how PHP-FPM works today, which means that
> is easier to port existing code to, especially existing code that has lots
> of globals or hidden globals.  (Eg, Laravel.)  That may or may not make it
> the better model overall, I don't know, but it's the more-similar model.
>
> All that said, the idea of allowing a "persistent HTTP handler process"
> SAPI, "persistent Queue handler process" SAPI, and "persistent cron handler
> process" SAPI (or whatever combination of persistent processes) to all run
> side by side with the same code base but different entry point scripts
> is...  Hot.  If we can do something that would enable that kind of runtime
> model, I am very much here for that.
>

What you wrote sounds like some good points (as usual).
I'm not an expert (yet!) but was playing around with some callable trying
to mimic ASGI
https://github.com/brzuchal/asgi-playground/blob/main/app.php#L26-L37

What I think currently (maybe too hurry, but...) is that this kind of
approach is flexible enough to handle in easy way many SAPIs which identify
to app their capabilities,
and the app decides how and what can handle `$scope['type']` in the example
code.

I know there is a Runtime library, that tries to integrate
Symfony/Laaravel to many SAPIs, but as far as I understood the discussion
went to figure out if there is some kind of standard approach that could be
shaped under the PHP umbrella.

Maybe this is just a temporary fascination about ASGI solution, could be.
If this is not in the scope of interest of anyone then forgive me, I won't
bother anymore.

Cheers,
--
Michał Marcin Brzuchalski


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Larry Garfield
On Sat, Dec 30, 2023, at 4:53 AM, Rowan Tommins wrote:
> On 30 December 2023 09:59:07 GMT, Robert Landers 
>  wrote:
>>For this to happen in PHP Core, there would need to be request objects
>>instead of a global state.
>
> Again, the representation as objects isn't a key requirement. Python's 
> WSGI spec simply has a dictionary (read: associative array) of the 
> environment based on CGI. The application might well turn that into a 
> more powerful object, but standardisation of such wasn't considered a 
> pre-requisite, and would actually have hampered ASGI, where not all 
> events represent an HTTP request.
>
> The key requirement is that you have some way of passing the current 
> request and response around as scoped variables, not global state. 
> That's essential for any kind of concurrent run-time (async, 
> thread-aware, etc).
>
> An event / subscriber model fits well with that: the local scope for 
> each request is set up by an invocation of the callback with defined 
> parameters and return value.
>
> Funnily enough, the example of a worker script for FrankenPHP does both 
> things: it sends each request to the same application "handle" 
> callback, passing in the super-global arrays as parameters to be used 
> as non-global state. https://frankenphp.dev/docs/worker/#custom-apps So 
> really all I'm arguing is that a few more lines of that PHP example be 
> moved into the C implementation, so that the user only needs to provide 
> that inner callable, not the outer while loop.

So you're suggesting something like:

$app->initializeStuffHowever();
set_event_handler(Closure $handler);
// Script blocks here until a sigkill is received, or something.

I think there's an important distinction that is getting missed in the above 
discussion, beyond the push-vs-pull question.  FrankenPHP, as I understand it, 
pre-boots multiple worker processes, keeps them in memory, and then handles 
each request in its own process.  Swoole, Amp/React/Revolt, and friends have 
only a single process running at all, and make use of async to simulate 
multiple simultaneous requests, a la NodeJs.  That means mutable global 
variables in the FrankenPHP model still won't leak between parallel requests, 
whereas they absolutely would/do in a Swole/Revolt world.

I'm not going to call one of those better or worse (I don't have enough 
experience with either to say), but they are different beasts for which first 
class support would be different SAPIs either way.  They're not mutually 
exclusive thanks to Fibers (which mean you don't need the entire call stack to 
be async), but you would want to pick one or the other as primary runner mode 
of an application.  Let's keep that in mind when making comparisons.

The Franken-model is closer to how PHP-FPM works today, which means that is 
easier to port existing code to, especially existing code that has lots of 
globals or hidden globals.  (Eg, Laravel.)  That may or may not make it the 
better model overall, I don't know, but it's the more-similar model.

All that said, the idea of allowing a "persistent HTTP handler process" SAPI, 
"persistent Queue handler process" SAPI, and "persistent cron handler process" 
SAPI (or whatever combination of persistent processes) to all run side by side 
with the same code base but different entry point scripts is...  Hot.  If we 
can do something that would enable that kind of runtime model, I am very much 
here for that.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Rowan Tommins
On 30 December 2023 09:59:07 GMT, Robert Landers  
wrote:
>For this to happen in PHP Core, there would need to be request objects
>instead of a global state.

Again, the representation as objects isn't a key requirement. Python's WSGI 
spec simply has a dictionary (read: associative array) of the environment based 
on CGI. The application might well turn that into a more powerful object, but 
standardisation of such wasn't considered a pre-requisite, and would actually 
have hampered ASGI, where not all events represent an HTTP request.

The key requirement is that you have some way of passing the current request 
and response around as scoped variables, not global state. That's essential for 
any kind of concurrent run-time (async, thread-aware, etc).

An event / subscriber model fits well with that: the local scope for each 
request is set up by an invocation of the callback with defined parameters and 
return value.

Funnily enough, the example of a worker script for FrankenPHP does both things: 
it sends each request to the same application "handle" callback, passing in the 
super-global arrays as parameters to be used as non-global state. 
https://frankenphp.dev/docs/worker/#custom-apps So really all I'm arguing is 
that a few more lines of that PHP example be moved into the C implementation, 
so that the user only needs to provide that inner callable, not the outer while 
loop.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Michał Marcin Brzuchalski
Hi Robert,

sob., 30 gru 2023, 10:59 użytkownik Robert Landers 
napisał:

> > > - FrankenPHP expects the user to manage the main event loop ...
> > >
> > >
> > > This isn't exact. FrankenPHP does manage the event loop (the Go
> > > runtime manages it - through a channel - under the hood).
> >
> >
> > Perhaps "event loop" was the wrong term; what I was highlighting is that
> > to use FrankenPHP or RoadRunner, you have to write a while loop, which
> > explicitly handles one request at a time. In Swoole, there is no such
> > loop: you register event handlers and then call $server->run() once.
> > Similarly, WSGI mandates that the server "invokes the application
> > callable once for each request it receives from an HTTP client".
> >
> > It's a distinction of pull/poll (the application must actively block
> > until next request) vs push/subscribe (the application is passively
> > invoked whenever needed).
>
> I think these models have different capabilities: A pull/poll model is
> quite simple, while a subscription model is usually more complex.
>
> With something simple like in FrankenPHP, creating a Queue SAPI, a
> WebSocket SAPI, etc isn't far off, where someone writes some PHP to
> consume a queue or websocket connections.
>
> > > I already replied to Crell about that. It will totally possible to
> > > expose more complex HTTP message objects in the future,
> > > but PHP currently lacks such objects. The only things we have are
> > > superglobals (which are more or less similar to CGI variables, as done
> > > in WSGI) and streams. It's why we're using them.
> >
> >
> > The use of objects vs arrays wasn't the main difference I was trying to
> > highlight there, but rather the overall API of how information gets into
> > and out of the application. FrankenPHP is the only server listed which
> > needs to reset global state on each request, because the others
> > (including Python WSGI and ASGI) use non-global variables for both input
> > and output.
> >
> > I notice that the Laravel Octane adaptor for FrankenPHP takes that
> > global state and immediately converts it into non-global variables for
> > consumption by the application.
>
> For this to happen in PHP Core, there would need to be request objects
> instead of a global state. If an RFC implementing PSR
> requests/responses in Core is a pre-requisite for enabling what we're
> discussing here, I'd personally be all for that (as would a very large
> chunk of the PHP community, IMHO). I personally think this is a
> chicken/egg type of problem though. It doesn't make sense to have
> request/response objects right now, and I get the feeling that people
> would only support worker mode primitives if there were request
> objects... so, it might make sense to build a v1 of the worker mode
> primitives and then iterate towards request objects, because then
> there would be an actual need for them.
>

That is certainly not true. Looking at WSGI or ASGI there is no need for
request response objects. These can be provided in userland which gives
more flexibility cause of different rules governing over bc break policy in
PHP core.

Name one true argument to convince me in this topic and I may change my
mind.
For the years I had the same impression but on low level the primitives are
more flexible and we all know that.

Cheers,
Michał Marcin Brzuchalski

>


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Robert Landers
> > - FrankenPHP expects the user to manage the main event loop ...
> >
> >
> > This isn't exact. FrankenPHP does manage the event loop (the Go
> > runtime manages it - through a channel - under the hood).
>
>
> Perhaps "event loop" was the wrong term; what I was highlighting is that
> to use FrankenPHP or RoadRunner, you have to write a while loop, which
> explicitly handles one request at a time. In Swoole, there is no such
> loop: you register event handlers and then call $server->run() once.
> Similarly, WSGI mandates that the server "invokes the application
> callable once for each request it receives from an HTTP client".
>
> It's a distinction of pull/poll (the application must actively block
> until next request) vs push/subscribe (the application is passively
> invoked whenever needed).

I think these models have different capabilities: A pull/poll model is
quite simple, while a subscription model is usually more complex.

With something simple like in FrankenPHP, creating a Queue SAPI, a
WebSocket SAPI, etc isn't far off, where someone writes some PHP to
consume a queue or websocket connections.

> > I already replied to Crell about that. It will totally possible to
> > expose more complex HTTP message objects in the future,
> > but PHP currently lacks such objects. The only things we have are
> > superglobals (which are more or less similar to CGI variables, as done
> > in WSGI) and streams. It's why we're using them.
>
>
> The use of objects vs arrays wasn't the main difference I was trying to
> highlight there, but rather the overall API of how information gets into
> and out of the application. FrankenPHP is the only server listed which
> needs to reset global state on each request, because the others
> (including Python WSGI and ASGI) use non-global variables for both input
> and output.
>
> I notice that the Laravel Octane adaptor for FrankenPHP takes that
> global state and immediately converts it into non-global variables for
> consumption by the application.

For this to happen in PHP Core, there would need to be request objects
instead of a global state. If an RFC implementing PSR
requests/responses in Core is a pre-requisite for enabling what we're
discussing here, I'd personally be all for that (as would a very large
chunk of the PHP community, IMHO). I personally think this is a
chicken/egg type of problem though. It doesn't make sense to have
request/response objects right now, and I get the feeling that people
would only support worker mode primitives if there were request
objects... so, it might make sense to build a v1 of the worker mode
primitives and then iterate towards request objects, because then
there would be an actual need for them.

Robert Landers
Software Engineer
Utrecht NL

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-30 Thread Michał Marcin Brzuchalski
Hi Rowan,

pt., 29 gru 2023 o 23:56 Rowan Tommins  napisał(a):

> On 29/12/2023 21:14, Kévin Dunglas wrote:
> ...
> The use of objects vs arrays wasn't the main difference I was trying to
> highlight there, but rather the overall API of how information gets into
> and out of the application. FrankenPHP is the only server listed which
> needs to reset global state on each request, because the others
> (including Python WSGI and ASGI) use non-global variables for both input
> and output.
>

I wasn't aware of ASGI, in the past I read about WSGI and noticed a PHP
connector allowing the PHP app to run inside the WSGI server.
I read most of the spec
https://asgi.readthedocs.io/en/latest/specs/index.html yesterday and it
sounds like a really solid solution.
Personally, I'd love to see something similar for PHP.
It'd clearly be something different from the usual PHP app where global
$_GET|POST variables carry the HTTP request input.
Solution taken by Python in fact is about returning a callable fulfilling a
specific signature no matter if this is a simple function, closure or
Object implementing __invoke function - and this gives much flexibility.
I believe that considering the fact that ASGI provides an API for HTTP
interaction including WebSockets that could only benefit to PHP ecosystem.

In the past, I was thinking about something similar to adopting WSGI but
was not aware of ASGI.

Cheers,
Michał Marcin Brzuchalski


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-29 Thread Rowan Tommins

On 29/12/2023 21:14, Kévin Dunglas wrote:
On Fri, Dec 29, 2023 at 8:14 PM Rowan Tommins 
 wrote:


- FrankenPHP expects the user to manage the main event loop ...


This isn't exact. FrankenPHP does manage the event loop (the Go 
runtime manages it - through a channel - under the hood).



Perhaps "event loop" was the wrong term; what I was highlighting is that 
to use FrankenPHP or RoadRunner, you have to write a while loop, which 
explicitly handles one request at a time. In Swoole, there is no such 
loop: you register event handlers and then call $server->run() once. 
Similarly, WSGI mandates that the server "invokes the application 
callable once for each request it receives from an HTTP client".


It's a distinction of pull/poll (the application must actively block 
until next request) vs push/subscribe (the application is passively 
invoked whenever needed).



I already replied to Crell about that. It will totally possible to 
expose more complex HTTP message objects in the future,
but PHP currently lacks such objects. The only things we have are 
superglobals (which are more or less similar to CGI variables, as done 
in WSGI) and streams. It's why we're using them.



The use of objects vs arrays wasn't the main difference I was trying to 
highlight there, but rather the overall API of how information gets into 
and out of the application. FrankenPHP is the only server listed which 
needs to reset global state on each request, because the others 
(including Python WSGI and ASGI) use non-global variables for both input 
and output.


I notice that the Laravel Octane adaptor for FrankenPHP takes that 
global state and immediately converts it into non-global variables for 
consumption by the application.




I'm not sure what you mean by "async PHP environment".



OpenSwoole, AMPHP, ReactPHP, etc - servers which expose concurrency 
directly to the user of PHP. In those environments, global state isn't 
just reused between consecutive requests, it's shared between multiple 
requests running concurrently, so a global "current request" and 
"current response" have no meaning.



WebSockets and WebTransport are a different kind of beast, they are 
much lower level than HTTP and will require a different API anyway 
(and probably a lot of other adaptations in core) to be supported in PHP.



WebSocket support in PHP is just as real as worker modes and 
asynchronous concurrency.


Swoole has a WebSocket implementation included in core 
[https://openswoole.com/docs/modules/swoole-websocket-server] and 
Roadrunner has a plugin for it 
[https://roadrunner.dev/docs/plugins-centrifuge/current] In both cases 
(and in ASGI), the same basic API is used as with HTTP, but using a more 
general concept of "events" in place of "requests".


Other PHP implementations include Ratchet [http://socketo.me/] and AMPHP 
Websocket Server [https://github.com/amphp/websocket-server].



Note that both async and WebSockets were mentioned as possible "forward 
compatibility". If we're talking about "next generation SAPIs", these 
are the kinds of features that people will be - and already are - 
developing; so it seems foolish not to at least consider them when 
designing new baseline APIs.



Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-29 Thread Kévin Dunglas
On Fri, Dec 29, 2023 at 8:14 PM Rowan Tommins 
wrote:

> - FrankenPHP expects the user to manage the main event loop, repeatedly
> passing the server a function to be called once; it doesn't pass
> anything into or out of the userland handler, instead resetting global
> state to mimic a non-worker environment
> [https://frankenphp.dev/docs/worker/#custom-apps]
>

This isn't exact. FrankenPHP does manage the event loop (the Go runtime
manages it - through a channel - under the hood).
The frankenphp_handle_request() pauses the thread until the Go runtime
gives back control to the C thread (when a request is dispatched to this
worker).
It's actually very similar to WSGI.

As I explained in my previous messages, it's expected that other SAPIs
handle the event loop too (using the primitives provided by the language
they are written in).


> - RoadRunner doesn't use a callback at all, instead providing methods to
> await a request and provide a response; it directly uses PSR-7 and
> PSR-17 objects [https://roadrunner.dev/docs/php-worker/current/en]
> - OpenSwoole manages the main loop itself, and uses lifecycle events to
> interface to userland code; the HTTP 'Request' event is passed custom
> Request and Response objects
> [https://openswoole.com/docs/modules/swoole-http-server-on-request]
>

I already replied to Crell about that. It will totally possible to expose
more complex HTTP message objects in the future,
but PHP currently lacks such objects. The only things we have are
superglobals (which are more or less similar to CGI variables, as done in
WSGI) and streams. It's why we're using them.
If PHP adds a higher-level API at some point, we'll be able to upgrade this
part as every other part of the PHP code base. But it's an unrelated topic:
having such higher-level representations of HTTP messages would be
beneficial both in "normal" and in "worker" mode.


> it would be adapted for an async PHP environment, or with WebSockets,
> for instance.
>

I'm not sure what you mean by "async PHP environment".
WebSockets and WebTransport are a different kind of beast, they are much
lower level than HTTP and will require a different API anyway (and probably
a lot of other adaptations in core) to be supported in PHP.
In Go, for instance, the WebSocket and WebTransport APIs aren't the same as
the HTTP API.

Best regards,


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-29 Thread Rowan Tommins

On 23/12/2023 20:34, Kévin Dunglas wrote:

In addition to sharing code, maintenance, performance optimization, etc.,
the existence of a common infrastructure would standardize the way worker
scripts are created and provide a high-level PHP API for writing worker
scripts that work with all SAPIs that rely on this new feature.



While this seems like a noble aim, there doesn't seem to be much 
consensus on what such an API should look like; from what I can see:


- FrankenPHP expects the user to manage the main event loop, repeatedly 
passing the server a function to be called once; it doesn't pass 
anything into or out of the userland handler, instead resetting global 
state to mimic a non-worker environment 
[https://frankenphp.dev/docs/worker/#custom-apps]
- RoadRunner doesn't use a callback at all, instead providing methods to 
await a request and provide a response; it directly uses PSR-7 and 
PSR-17 objects [https://roadrunner.dev/docs/php-worker/current/en]
- OpenSwoole manages the main loop itself, and uses lifecycle events to 
interface to userland code; the HTTP 'Request' event is passed custom 
Request and Response objects 
[https://openswoole.com/docs/modules/swoole-http-server-on-request]


It also seems relevant to mention the situation in Python:

- WSGI specifies a Python-level interface between a web server and a web 
application / framework. The server side is expected to provide the 
event loop (unlike in FrankenPHP), and passes the application an 
environment dictionary (based on CGI) and a start_response callback. 
[https://peps.python.org/pep-/]
- The newer ASGI generalises this interface into an asynchronous event 
handling system, including support for WebSockets. 
[https://asgi.readthedocs.io/en/latest/introduction.html]


Out of all of these, the FrankenPHP approach seems to be the most basic, 
providing good backwards compatibility with PHP's normal "shared 
nothing" approach, but not much forwards compatibility - I can't see how 
it would be adapted for an async PHP environment, or with WebSockets, 
for instance. I'm sceptical how many SAPIs would actually implement it, 
rather than providing more powerful APIs.


Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-26 Thread Tim Düsterhus

Hi

On 12/25/23 19:56, Jordan LeDoux wrote:

So you want to introduce a SAPI that doesn't work with any of the existing
HTTP solutions people use that only supports HTTP requests? Or am I
misunderstanding something?

This sounds a bit like you want to merge in a tool that is designed for
your personal product directly into core. FrankenPHP may be incredible and
awesome, but the world runs on Apache and Nginx for HTTP requests.



My understanding of the proposal in very simplified language is: A new 
function shall be added to be implemented by SAPIs that are capable of 
implementing the function correctly.


This function effectively:

1. Flushes the pending headers (header() calls) and body (if any).
2. Blocks until a request arrives.
3. Sets the superglobals ($_GET, $_POST, ...) to the request's values.
4. Sets the php://input stream to that request's body.
5. Sets up default headers (e.g. x-powered-by, if enabled).

Best regard
Tim Düsterhus

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Alexander Pravdin
>
> So you want to introduce a SAPI that doesn't work with any of the existing
> HTTP solutions people use that only supports HTTP requests? Or am I
> misunderstanding something?
>
> This sounds a bit like you want to merge in a tool that is designed for
> your personal product directly into core. FrankenPHP may be incredible and
> awesome, but the world runs on Apache and Nginx for HTTP requests.
>
>
To be honest, after trying RoadRunner (an alternative to FrankenPHP), I'm
using it for all my projects if the framework and packages have no issues
with this execution model. Only old codebases with extensive usage of
global variables and stateful services are at risk. If you stick with
readonly classes and follow best DI practices, there will be minimum to no
issues. Symfomy is actively propagating safe coding styles. So from my POV
it is not a problem that a new execution model will be supported. If your
code is not compatible - then this is your problem. It is normal that some
code may not work properly in different modes. The fact that the world is
running on Apache and Nginx doesn't mean this will be forever with no
alternatives. The fact that there are multiple projects with the same goal
shows that there is a big demand for PHP speedup. And there are no visible
alternatives except a worker mode. IMO.


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Pierre Joye
Hello,

On Tue, Dec 26, 2023, 1:56 AM Jordan LeDoux  wrote:

>
> So you want to introduce a SAPI that doesn't work with any of the existing
> HTTP solutions people use that only supports HTTP requests? Or am I
> misunderstanding something?
>
> This sounds a bit like you want to merge in a tool that is designed for
> your personal product directly into core. FrankenPHP may be incredible and
> awesome, but the world runs on Apache and Nginx for HTTP requests.



The world was running on cgi when php was created and a few years after.
Then the world was running on threads/apache. Then it ran in fcgi and
finally fcgi fpm for the last few years.

Other languages support this since quite some time. Projects like reactphp,
swoole and the likes provide userland versions of it and the benefits are
clear. They even worked together recently to get a common core. Many
(large) projects out there already support FrankenPHP, the needs are there.

FrankenPhp and a worker mode go beyond the classical php usages we had.
Desktop applications or IoT are getting more common (see laravel's
nativephp f.e.). I have done something similar for one of our products
using embedded sapi but how it is done using frankenphp would be an order
of magnitude better.

Having the complex parts in the core us a good start to experiment, adapt.
Later a core sapi may be added, we cannot know without trying and let the
community uses it.

best,
Pierre


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Lanre Waju
Why not just build this into the embed sapi instead? since its only for 
third party sapis?


On 2023-12-23 1:34 p.m., Kévin Dunglas wrote:

Hello and Merry Christmas!

One of the main features of FrankenPHP is its worker mode, which lets you
keep a PHP application in memory to handle multiple HTTP requests.

Worker modes are becoming increasingly popular in the PHP world. Symfony
(Runtime Component), Laravel (Octane), and many projects based on these
frameworks (API Platform, Sulu...) now support a worker mode.

In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
engines supporting worker modes.

According to benchmarks, worker modes can improve the performance of PHP
applications by up to 15 times.
In addition to FrankenPHP, which is basically a SAPI for Go's integrated
web server, a new generation of SAPIs is currently under development.
Several SAPIs written in Rust (including one by the RoadRunner team) are
currently under development.

These SAPIs, along with existing SAPIs, could benefit from a shared
infrastructure to build worker modes.



The FrankenPHP code is written and should be easy to move around in PHP
itself, to enable other SAPIs to use it.

In addition to sharing code, maintenance, performance optimization, etc.,
the existence of a common infrastructure would standardize the way worker
scripts are created and provide a high-level PHP API for writing worker
scripts that work with all SAPIs that rely on this new feature.

SAPIs will still have to handle fetching requests from the web server and
pausing the worker to wait for new requests (in FrankenPHP, we use
GoRoutines for this, in Rust or C, other primitives will have to be used),
but almost everything else could be shared.

For reference, here's the FrankenPHP code I propose to integrate into
libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245

The public API is documented here:
https://frankenphp.dev/docs/worker/#custom-apps

I'd like to hear what the community thinks about this. Would you be
interested in this functionality in PHP? Should I work on an RFC?

If there's interest, I can work on a patch.

Cheers,


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Jakub Zelenka
Hi,

On Tue, Dec 26, 2023 at 12:09 AM Robert Landers 
wrote:

> Hi Jakub,
>
> > I have been thinking about something similar for FPM and if you had some
> > sort pool manager process, you could maybe do some sort of initial
> > execution but then it gets really tricky especially with sharing
> resources
> > and managing connections. I think it would be a big can of worms so I
> don't
> > think this is going to happen anytime soon.
>
> It's already happening. Most libraries (particularly popular ones in
> the Symfony/Laravel world) already support most of this
> out-of-the-box. I love stateless servers, but sometimes a stateful
> server is better. What is really nice about worker mode is that you
> can actually have a PHP-native in-memory database that only exists for
> as long as the worker is running (I do this for some unit tests).
>
>
This was just about FPM. What I meant that this is not going to be
supported by FPM anytime soon if ever.


> > I could imaging that there will
> > be similar issues for Apache prefork which is likely the most used MPM
> for
> > legacy apps. Effectively it means that this function won't be working on
> > most installations as two of the likely most used SAPI's won't support
> it.
> > I think it should be pretty clear from the beginning.
>
> Most people are familiar with fastcgi_finish_request() and there are
> some built-in SAPI's that don't support it. I don't think that just
> because it won't start out with full support, it should be discarded.
>
>
I didn't mean that it shouldn't be added. It should just be clear from the
beginning that this will be for limited set of SAPIs.


> > It would be also good to put together some base design PR for this as
> > currently SAPI common functions are implemented separately in each SAPI
> > (e.g. apache_request_headers). From the linked functionality, it is is
> not
> > a big amount of code and seems somehow specific to the FrankenPHP so why
> > couldn't each SAPI just implement this function separately? I know that
> > this is not ideal but it's what is already used for
> apache_request_headers.
> > I think otherwise you would need some hooking mechanism that should have
> > some default (which would probably just throw exception) because it is
> not
> > going to be implemented by all SAPI's. I think it would be really good if
> > you could provide more details about planned implementation for this.
>
> Most (all?) modern SAPI (lightspeed, roadrunner, etc) implements
> fastcgi_finish_request(), even if no fastcgi is involved, simply
> because of backward compatibility. It'd be great to actually bikeshed
> a decent name and syntax/semantics before something popular comes
> along and forces us all to use frankenphp_handle_request() or
> something, simply because of backward compatibility.
>

I agree that coming up with some sensible name and API would be a good
think even though it will have limited use in core. And if it gives us some
coverage of embed SAPI (libphp), then it's even better.

Cheers

Jakub


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Jakub Zelenka
On Mon, Dec 25, 2023 at 7:06 PM Kévin Dunglas  wrote:

>
> On Mon, Dec 25, 2023 at 6:30 PM Jakub Zelenka  wrote:
>
>>
>>
>> On Mon, Dec 25, 2023 at 12:34 PM Kévin Dunglas  wrote:
>>
>>> On Sun, Dec 24, 2023 at 4:21 PM Larry Garfield 
>>> wrote:
>>>
>>> In practice, I want to understand the implications for user-space code.
>>> > Does this mean FPM could be configured in a way to execute a file like
>>> that
>>> > shown in the docs page above?  Or would it only work with third party
>>> SAPIs
>>> > like FrankenPHP?
>>>
>>>
>>> In theory, PHP-FPM and the Apache module could - like all other SAPIs -
>>> be
>>> enhanced to add a worker mode operating as described in the FrankenPHP
>>> doc
>>> thanks to these new primitives.
>>>
>>
>> I have been thinking about something similar for FPM and if you had some
>> sort pool manager process, you could maybe do some sort of initial
>> execution but then it gets really tricky especially with sharing resources
>> and managing connections. I think it would be a big can of worms so I don't
>> think this is going to happen anytime soon. I could imaging that there will
>> be similar issues for Apache prefork which is likely the most used MPM for
>> legacy apps. Effectively it means that this function won't be working on
>> most installations as two of the likely most used SAPI's won't support it.
>> I think it should be pretty clear from the beginning.
>>
>>
>>> However, I suggest doing this as a second step, because as described in
>>> my
>>> first post, it will still be the responsibility of each SAPI to manage
>>> long-running processes and communication with them. This is simple to do
>>> with Go's GoRoutine and Rust's asynchronous runtimes such as Tokio, it's
>>> definitely more difficult in cross-platform C. I suggest starting by
>>> adding
>>> the primitives to libphp, then we'll see how to exploit them (and whether
>>> it's worthwhile) in the built-in SAPIs.
>>>
>>
>> The problem with this is that we would add some code that won't be used
>> by any of the built in SAPI which means that that we won't be able to have
>> automated tests for this. So the minimum should be to have at least one
>> core SAPI supporting this new functionality. I wouldn't mind if it's just a
>> SAPI for testing purpose which might be actually useful for testing embed
>> SAPI code. I think that should be a requirement for accepting a PR
>> introducing this.
>>
>> It would be also good to put together some base design PR for this as
>> currently SAPI common functions are implemented separately in each SAPI
>> (e.g. apache_request_headers). From the linked functionality, it is is not
>> a big amount of code and seems somehow specific to the FrankenPHP so why
>> couldn't each SAPI just implement this function separately? I know that
>> this is not ideal but it's what is already used for apache_request_headers.
>> I think otherwise you would need some hooking mechanism that should have
>> some default (which would probably just throw exception) because it is not
>> going to be implemented by all SAPI's. I think it would be really good if
>> you could provide more details about planned implementation for this.
>>
>>
>>> I personally have less interest in working on FPM/CGI/mod_php as the
>>> other
>>> possibilities offered by modern SAPIs like FrankenPHP are more important
>>> (better deployment experience as you have a single static binary or
>>> Docker
>>> image, Early Hints support, high-quality native HTTP/3 server etc)
>>>
>>>
>> Except that those are all threaded SAPIs so they offer less separation
>> and protection against application crashes in addition to the fact that
>> thread management in PHP still has got its own issues. They are certainly
>> some advantages especially for thin services but if you have huge monolith
>> codebase like some big CMS and other projects, then I would probably stick
>> with process separation model.
>>
>> Cheers
>>
>> Jakub
>>
>
> Sure, the main targets are new SAPIs like FrankenPHP and the one in Rust
> developed by the RoadRunner team. I thought it was clear in my previous
> messages but I'll be glad to make it bold in the RFC.
>

The way how I read was that this would be eventually supported by all SAPIs
which I think is not likely going to be the case.


> Automated tests (likely through a test SAPI) will definitely be needed.
> Throwing if the current SAPI doesn't support (yet) the new userland
> function looks sensitive.
>
>
+1


> Couldn't this shared code be put in "main", as it could (theoretically, I
> agree that it will be hard to do for existing core SAPIs) be used by all
> SAPIs?
>

The main does not have a module but it could be probably added to standard
ext like it's the case for other functionality related to main.

Cheers

Jakub


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Robert Landers
Hi Jakub,

> I have been thinking about something similar for FPM and if you had some
> sort pool manager process, you could maybe do some sort of initial
> execution but then it gets really tricky especially with sharing resources
> and managing connections. I think it would be a big can of worms so I don't
> think this is going to happen anytime soon.

It's already happening. Most libraries (particularly popular ones in
the Symfony/Laravel world) already support most of this
out-of-the-box. I love stateless servers, but sometimes a stateful
server is better. What is really nice about worker mode is that you
can actually have a PHP-native in-memory database that only exists for
as long as the worker is running (I do this for some unit tests).

> I could imaging that there will
> be similar issues for Apache prefork which is likely the most used MPM for
> legacy apps. Effectively it means that this function won't be working on
> most installations as two of the likely most used SAPI's won't support it.
> I think it should be pretty clear from the beginning.

Most people are familiar with fastcgi_finish_request() and there are
some built-in SAPI's that don't support it. I don't think that just
because it won't start out with full support, it should be discarded.

> It would be also good to put together some base design PR for this as
> currently SAPI common functions are implemented separately in each SAPI
> (e.g. apache_request_headers). From the linked functionality, it is is not
> a big amount of code and seems somehow specific to the FrankenPHP so why
> couldn't each SAPI just implement this function separately? I know that
> this is not ideal but it's what is already used for apache_request_headers.
> I think otherwise you would need some hooking mechanism that should have
> some default (which would probably just throw exception) because it is not
> going to be implemented by all SAPI's. I think it would be really good if
> you could provide more details about planned implementation for this.

Most (all?) modern SAPI (lightspeed, roadrunner, etc) implements
fastcgi_finish_request(), even if no fastcgi is involved, simply
because of backward compatibility. It'd be great to actually bikeshed
a decent name and syntax/semantics before something popular comes
along and forces us all to use frankenphp_handle_request() or
something, simply because of backward compatibility.

I think this functionality unlocks some really cool potential powers
(in-memory databases for development, connection pooling without an
extension, etc) and it's worth at least seriously considering
implementing it in core.

- Rob

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Kévin Dunglas
On Mon, Dec 25, 2023 at 7:56 PM Jordan LeDoux 
wrote:

>
>
> On Mon, Dec 25, 2023 at 8:19 AM Kévin Dunglas  wrote:
>
>>
>> On Sun, Dec 24, 2023 at 10:44 PM Jordan LeDoux 
>> wrote:
>>
>>>
>>>
>>> On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:
>>>
 Hello and Merry Christmas!

 One of the main features of FrankenPHP is its worker mode, which lets
 you
 keep a PHP application in memory to handle multiple HTTP requests.

 Worker modes are becoming increasingly popular in the PHP world. Symfony
 (Runtime Component), Laravel (Octane), and many projects based on these
 frameworks (API Platform, Sulu...) now support a worker mode.

 In addition to FrankenPHP, projects such as RoadRunner and Swoole
 provide
 engines supporting worker modes.

 According to benchmarks, worker modes can improve the performance of PHP
 applications by up to 15 times.
 In addition to FrankenPHP, which is basically a SAPI for Go's integrated
 web server, a new generation of SAPIs is currently under development.
 Several SAPIs written in Rust (including one by the RoadRunner team) are
 currently under development.

 These SAPIs, along with existing SAPIs, could benefit from a shared
 infrastructure to build worker modes.



 The FrankenPHP code is written and should be easy to move around in PHP
 itself, to enable other SAPIs to use it.

 In addition to sharing code, maintenance, performance optimization,
 etc.,
 the existence of a common infrastructure would standardize the way
 worker
 scripts are created and provide a high-level PHP API for writing worker
 scripts that work with all SAPIs that rely on this new feature.

 SAPIs will still have to handle fetching requests from the web server
 and
 pausing the worker to wait for new requests (in FrankenPHP, we use
 GoRoutines for this, in Rust or C, other primitives will have to be
 used),
 but almost everything else could be shared.

 For reference, here's the FrankenPHP code I propose to integrate into
 libphp:
 https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245

 The public API is documented here:
 https://frankenphp.dev/docs/worker/#custom-apps

 I'd like to hear what the community thinks about this. Would you be
 interested in this functionality in PHP? Should I work on an RFC?

 If there's interest, I can work on a patch.

 Cheers,
 --
 Kévin Dunglas

>>>
>>> Much like Larry, I'm curious what sort of scope you imagine for this.
>>> Are you imagining something that is geared specifically towards HTTP
>>> requests, or would this be a more generic "PHP Application Worker" that
>>> might be spawned to handle other types of applications? Could we have a
>>> worker listen to a specific port and respond to or handle all requests on
>>> that port/device?
>>>
>>> Jordan
>>>
>>
>> Ho Jordan,
>>
>> Yes, the scope I imagine is geared specifically towards HTTP requests.
>> Something more generic than common primitives for SAPIs and a shared public
>> API to handle HTTP requests with a long-running PHP worker script will be
>> hard to do outside of SAPIs because they depend on a lot of external
>> concerns such as the programming language the SAPI is using.
>>
>
> So you want to introduce a SAPI that doesn't work with any of the existing
> HTTP solutions people use that only supports HTTP requests? Or am I
> misunderstanding something?
>
> This sounds a bit like you want to merge in a tool that is designed for
> your personal product directly into core. FrankenPHP may be incredible and
> awesome, but the world runs on Apache and Nginx for HTTP requests.
>
> Jordan
>

As explained in the initial message and in my reply to Jakub, the main
targets are emerging SAPIs. We have no interest (quite the contrary) in
moving this code from FrankenPHP to PHP core (harder maintenance, slower
iterations as more collaboration will be involved...), but I do think that
having a "standard" and shared infrastructure and API for worker modes
between new generation SAPIs will be beneficial to the community as a whole
(no need - as at present - to write a different worker script for each
engine having a worker mode, sharing of optimizations, security patches
etc...).

We're talking roughly about a C function of a few dozen lines, not
something very big.


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Kévin Dunglas
On Mon, Dec 25, 2023 at 6:30 PM Jakub Zelenka  wrote:

>
>
> On Mon, Dec 25, 2023 at 12:34 PM Kévin Dunglas  wrote:
>
>> On Sun, Dec 24, 2023 at 4:21 PM Larry Garfield 
>> wrote:
>>
>> In practice, I want to understand the implications for user-space code.
>> > Does this mean FPM could be configured in a way to execute a file like
>> that
>> > shown in the docs page above?  Or would it only work with third party
>> SAPIs
>> > like FrankenPHP?
>>
>>
>> In theory, PHP-FPM and the Apache module could - like all other SAPIs - be
>> enhanced to add a worker mode operating as described in the FrankenPHP doc
>> thanks to these new primitives.
>>
>
> I have been thinking about something similar for FPM and if you had some
> sort pool manager process, you could maybe do some sort of initial
> execution but then it gets really tricky especially with sharing resources
> and managing connections. I think it would be a big can of worms so I don't
> think this is going to happen anytime soon. I could imaging that there will
> be similar issues for Apache prefork which is likely the most used MPM for
> legacy apps. Effectively it means that this function won't be working on
> most installations as two of the likely most used SAPI's won't support it.
> I think it should be pretty clear from the beginning.
>
>
>> However, I suggest doing this as a second step, because as described in my
>> first post, it will still be the responsibility of each SAPI to manage
>> long-running processes and communication with them. This is simple to do
>> with Go's GoRoutine and Rust's asynchronous runtimes such as Tokio, it's
>> definitely more difficult in cross-platform C. I suggest starting by
>> adding
>> the primitives to libphp, then we'll see how to exploit them (and whether
>> it's worthwhile) in the built-in SAPIs.
>>
>
> The problem with this is that we would add some code that won't be used by
> any of the built in SAPI which means that that we won't be able to have
> automated tests for this. So the minimum should be to have at least one
> core SAPI supporting this new functionality. I wouldn't mind if it's just a
> SAPI for testing purpose which might be actually useful for testing embed
> SAPI code. I think that should be a requirement for accepting a PR
> introducing this.
>
> It would be also good to put together some base design PR for this as
> currently SAPI common functions are implemented separately in each SAPI
> (e.g. apache_request_headers). From the linked functionality, it is is not
> a big amount of code and seems somehow specific to the FrankenPHP so why
> couldn't each SAPI just implement this function separately? I know that
> this is not ideal but it's what is already used for apache_request_headers.
> I think otherwise you would need some hooking mechanism that should have
> some default (which would probably just throw exception) because it is not
> going to be implemented by all SAPI's. I think it would be really good if
> you could provide more details about planned implementation for this.
>
>
>> I personally have less interest in working on FPM/CGI/mod_php as the other
>> possibilities offered by modern SAPIs like FrankenPHP are more important
>> (better deployment experience as you have a single static binary or Docker
>> image, Early Hints support, high-quality native HTTP/3 server etc)
>>
>>
> Except that those are all threaded SAPIs so they offer less separation and
> protection against application crashes in addition to the fact that thread
> management in PHP still has got its own issues. They are certainly some
> advantages especially for thin services but if you have huge monolith
> codebase like some big CMS and other projects, then I would probably stick
> with process separation model.
>
> Cheers
>
> Jakub
>

Sure, the main targets are new SAPIs like FrankenPHP and the one in Rust
developed by the RoadRunner team. I thought it was clear in my previous
messages but I'll be glad to make it bold in the RFC.
Automated tests (likely through a test SAPI) will definitely be needed.
Throwing if the current SAPI doesn't support (yet) the new userland
function looks sensitive.

Couldn't this shared code be put in "main", as it could (theoretically, I
agree that it will be hard to do for existing core SAPIs) be used by all
SAPIs?


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Jordan LeDoux
On Mon, Dec 25, 2023 at 8:19 AM Kévin Dunglas  wrote:

>
> On Sun, Dec 24, 2023 at 10:44 PM Jordan LeDoux 
> wrote:
>
>>
>>
>> On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:
>>
>>> Hello and Merry Christmas!
>>>
>>> One of the main features of FrankenPHP is its worker mode, which lets you
>>> keep a PHP application in memory to handle multiple HTTP requests.
>>>
>>> Worker modes are becoming increasingly popular in the PHP world. Symfony
>>> (Runtime Component), Laravel (Octane), and many projects based on these
>>> frameworks (API Platform, Sulu...) now support a worker mode.
>>>
>>> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
>>> engines supporting worker modes.
>>>
>>> According to benchmarks, worker modes can improve the performance of PHP
>>> applications by up to 15 times.
>>> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
>>> web server, a new generation of SAPIs is currently under development.
>>> Several SAPIs written in Rust (including one by the RoadRunner team) are
>>> currently under development.
>>>
>>> These SAPIs, along with existing SAPIs, could benefit from a shared
>>> infrastructure to build worker modes.
>>>
>>>
>>>
>>> The FrankenPHP code is written and should be easy to move around in PHP
>>> itself, to enable other SAPIs to use it.
>>>
>>> In addition to sharing code, maintenance, performance optimization, etc.,
>>> the existence of a common infrastructure would standardize the way worker
>>> scripts are created and provide a high-level PHP API for writing worker
>>> scripts that work with all SAPIs that rely on this new feature.
>>>
>>> SAPIs will still have to handle fetching requests from the web server and
>>> pausing the worker to wait for new requests (in FrankenPHP, we use
>>> GoRoutines for this, in Rust or C, other primitives will have to be
>>> used),
>>> but almost everything else could be shared.
>>>
>>> For reference, here's the FrankenPHP code I propose to integrate into
>>> libphp:
>>> https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>>>
>>> The public API is documented here:
>>> https://frankenphp.dev/docs/worker/#custom-apps
>>>
>>> I'd like to hear what the community thinks about this. Would you be
>>> interested in this functionality in PHP? Should I work on an RFC?
>>>
>>> If there's interest, I can work on a patch.
>>>
>>> Cheers,
>>> --
>>> Kévin Dunglas
>>>
>>
>> Much like Larry, I'm curious what sort of scope you imagine for this. Are
>> you imagining something that is geared specifically towards HTTP requests,
>> or would this be a more generic "PHP Application Worker" that might be
>> spawned to handle other types of applications? Could we have a worker
>> listen to a specific port and respond to or handle all requests on that
>> port/device?
>>
>> Jordan
>>
>
> Ho Jordan,
>
> Yes, the scope I imagine is geared specifically towards HTTP requests.
> Something more generic than common primitives for SAPIs and a shared public
> API to handle HTTP requests with a long-running PHP worker script will be
> hard to do outside of SAPIs because they depend on a lot of external
> concerns such as the programming language the SAPI is using.
>

So you want to introduce a SAPI that doesn't work with any of the existing
HTTP solutions people use that only supports HTTP requests? Or am I
misunderstanding something?

This sounds a bit like you want to merge in a tool that is designed for
your personal product directly into core. FrankenPHP may be incredible and
awesome, but the world runs on Apache and Nginx for HTTP requests.

Jordan


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Jakub Zelenka
On Mon, Dec 25, 2023 at 12:34 PM Kévin Dunglas  wrote:

> On Sun, Dec 24, 2023 at 4:21 PM Larry Garfield 
> wrote:
>
> In practice, I want to understand the implications for user-space code.
> > Does this mean FPM could be configured in a way to execute a file like
> that
> > shown in the docs page above?  Or would it only work with third party
> SAPIs
> > like FrankenPHP?
>
>
> In theory, PHP-FPM and the Apache module could - like all other SAPIs - be
> enhanced to add a worker mode operating as described in the FrankenPHP doc
> thanks to these new primitives.
>

I have been thinking about something similar for FPM and if you had some
sort pool manager process, you could maybe do some sort of initial
execution but then it gets really tricky especially with sharing resources
and managing connections. I think it would be a big can of worms so I don't
think this is going to happen anytime soon. I could imaging that there will
be similar issues for Apache prefork which is likely the most used MPM for
legacy apps. Effectively it means that this function won't be working on
most installations as two of the likely most used SAPI's won't support it.
I think it should be pretty clear from the beginning.


> However, I suggest doing this as a second step, because as described in my
> first post, it will still be the responsibility of each SAPI to manage
> long-running processes and communication with them. This is simple to do
> with Go's GoRoutine and Rust's asynchronous runtimes such as Tokio, it's
> definitely more difficult in cross-platform C. I suggest starting by adding
> the primitives to libphp, then we'll see how to exploit them (and whether
> it's worthwhile) in the built-in SAPIs.
>

The problem with this is that we would add some code that won't be used by
any of the built in SAPI which means that that we won't be able to have
automated tests for this. So the minimum should be to have at least one
core SAPI supporting this new functionality. I wouldn't mind if it's just a
SAPI for testing purpose which might be actually useful for testing embed
SAPI code. I think that should be a requirement for accepting a PR
introducing this.

It would be also good to put together some base design PR for this as
currently SAPI common functions are implemented separately in each SAPI
(e.g. apache_request_headers). From the linked functionality, it is is not
a big amount of code and seems somehow specific to the FrankenPHP so why
couldn't each SAPI just implement this function separately? I know that
this is not ideal but it's what is already used for apache_request_headers.
I think otherwise you would need some hooking mechanism that should have
some default (which would probably just throw exception) because it is not
going to be implemented by all SAPI's. I think it would be really good if
you could provide more details about planned implementation for this.


> I personally have less interest in working on FPM/CGI/mod_php as the other
> possibilities offered by modern SAPIs like FrankenPHP are more important
> (better deployment experience as you have a single static binary or Docker
> image, Early Hints support, high-quality native HTTP/3 server etc)
>
>
Except that those are all threaded SAPIs so they offer less separation and
protection against application crashes in addition to the fact that thread
management in PHP still has got its own issues. They are certainly some
advantages especially for thin services but if you have huge monolith
codebase like some big CMS and other projects, then I would probably stick
with process separation model.

Cheers

Jakub


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Kévin Dunglas
> Forgive my ignorance, but why no connection?  You mean the
> pre-worker-start part needs to avoid an SQL connection?  Why is that?  That
> would be something that needs to be super-well documented, and possibly
> some guards in place to prevent it, if there's no good way around it.
> (This is the sort of detail I'm thinking of, where I just don't know the
> implications but want to think through them as much as possible in advance,
> so that it can be "safe by design.")
>

Sorry, I made a typo. I mean "libraries must ensure that the connection
**is** active" (if the connection timeout has been reached, the library
must reconnect).
Your worker script will be long-running code, as in Java, Go, etc. So if it
depends on external services, it must check that the connection is still
active, and reconnect if necessary.
This is the default in most languages, but not in PHP (yet).

Do you have an intent or expectation of a worker-style SAPI being shipped
> with PHP itself, or for that to remain the domain of third parties?
>

As I tried to explain in my previous message, this could be nice, and
possible, but I don't plan to do it myself for now :)


> I mean more what implications would there be on how user-space code is
> written to be worker-SAPI-friendly.  (The SQL connection comment above, for
> example.)  I have not worked with any of the worker-ish tools so far
> myself, so other than "you'll need an alternate index.php for that", I
> don't have a good sense of what else I'd want to do differently to play
> nice with Franken and Friends.
>

As far as I know, there are no other implications than memory (and other
resources) leaks (https://laravel.com/docs/10.x/octane#managing-memory-leaks)
and timeout handling.


> The idea of combining fiber-based code with supported worker-mode runners
> sounds like a ridiculously cool future for PHP, but I don't know how windy
> that path is. :-)
>

That already works if you use FrankenPHP! Joe also experimented
successfully using the parallel extension instead of Fibers:
https://twitter.com/krakjoe/status/1587234661696245760


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Larry Garfield
On Mon, Dec 25, 2023, at 6:34 AM, Kévin Dunglas wrote:

> However, I suggest doing this as a second step, because as described in 
> my first post, it will still be the responsibility of each SAPI to 
> manage long-running processes and communication with them. This is 
> simple to do with Go's GoRoutine and Rust's asynchronous runtimes such 
> as Tokio, it's definitely more difficult in cross-platform C. I suggest 
> starting by adding the primitives to libphp, then we'll see how to 
> exploit them (and whether it's worthwhile) in the built-in SAPIs.
> I personally have less interest in working on FPM/CGI/mod_php as the 
> other possibilities offered by modern SAPIs like FrankenPHP are more 
> important (better deployment experience as you have a single static 
> binary or Docker image, Early Hints support, high-quality native HTTP/3 
> server etc), but I'd be happy to help if anyone wants to update these 
> SAPIs.

>> To what extent would user-space code run this way have to think about 
>> concurrency, shared memory, persistent SQL connections, etc?  Does it have 
>> any implications for fiber-using async code?
>
> Regarding concurrency, it doesn't change much (it's similar to existing 
> SAPI). Regarding memory and SQL connections, extra care is required. 
> Memory leaks (and other kinds of leaks) should be avoided (or workers 
> should restart from time to time, which is obviously a poorer 
> solution). Libraries maintaining SQL connections such as Doctrine or 
> Eloquent must ensure that the connection isn't active.

Forgive my ignorance, but why no connection?  You mean the pre-worker-start 
part needs to avoid an SQL connection?  Why is that?  That would be something 
that needs to be super-well documented, and possibly some guards in place to 
prevent it, if there's no good way around it.  (This is the sort of detail I'm 
thinking of, where I just don't know the implications but want to think through 
them as much as possible in advance, so that it can be "safe by design.")

> Fibers work as expected. There is a small limitation when using them 
> with Go (that is being tracked in the Go runtime, 
> https://frankenphp.dev/docs/known-issues/#fibers), but it's not related 
> to the C code of the worker mode, and this limitation shouldn't exist 
> for SAPIs not written in Go.
> 
>> Depending on the details, this could be like fibers but for 3rd party SAPIs 
>> (something about 4 people in the world actually care about directly, 
>> everyone else just uses Revolt, Amp, or React, but mostly it doesn't get 
>> used), or completely changing the way 90% of the market runs PHP, which 
>> means frameworks will likely adapt to use that model primarily or 
>> exclusively (ie, less of a need for a "compile" step as a generated 
>> container or dispatcher is just held in memory automatically already).  The 
>> latter sounds exciting to me, but I'm not sure which is your intent, so I 
>> don't know if I'm going too far with it. :-)
>
> My intent is that most SAPIs expose the same (or a very similar 
> interoperable) worker mode. So (I hope) that most PHP developers will 
> not have to deal with these primitives directly, but that it will allow 
> a new generation of super-fast PHP apps to be created. Most frameworks 
> already support that but require a lot of boilerplate code to support 
> the different existing engines. Standardizing will likely increase 
> adoption and will allow collaboration to make the low-level code that I 
> propose to move in libphp as fast, stable, and clean as possible.

Do you have an intent or expectation of a worker-style SAPI being shipped with 
PHP itself, or for that to remain the domain of third parties?

>> Please advise on what the implications would be for the non-SAPI-developing 
>> PHP devs out there.
>
> None, except that they will be able to use the new handle_request() 
> function to create a worker script if supported by the SAPI they use.

I mean more what implications would there be on how user-space code is written 
to be worker-SAPI-friendly.  (The SQL connection comment above, for example.)  
I have not worked with any of the worker-ish tools so far myself, so other than 
"you'll need an alternate index.php for that", I don't have a good sense of 
what else I'd want to do differently to play nice with Franken and Friends.

The idea of combining fiber-based code with supported worker-mode runners 
sounds like a ridiculously cool future for PHP, but I don't know how windy that 
path is. :-)

--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Kévin Dunglas
On Sun, Dec 24, 2023 at 10:44 PM Jordan LeDoux 
wrote:

>
>
> On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:
>
>> Hello and Merry Christmas!
>>
>> One of the main features of FrankenPHP is its worker mode, which lets you
>> keep a PHP application in memory to handle multiple HTTP requests.
>>
>> Worker modes are becoming increasingly popular in the PHP world. Symfony
>> (Runtime Component), Laravel (Octane), and many projects based on these
>> frameworks (API Platform, Sulu...) now support a worker mode.
>>
>> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
>> engines supporting worker modes.
>>
>> According to benchmarks, worker modes can improve the performance of PHP
>> applications by up to 15 times.
>> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
>> web server, a new generation of SAPIs is currently under development.
>> Several SAPIs written in Rust (including one by the RoadRunner team) are
>> currently under development.
>>
>> These SAPIs, along with existing SAPIs, could benefit from a shared
>> infrastructure to build worker modes.
>>
>>
>>
>> The FrankenPHP code is written and should be easy to move around in PHP
>> itself, to enable other SAPIs to use it.
>>
>> In addition to sharing code, maintenance, performance optimization, etc.,
>> the existence of a common infrastructure would standardize the way worker
>> scripts are created and provide a high-level PHP API for writing worker
>> scripts that work with all SAPIs that rely on this new feature.
>>
>> SAPIs will still have to handle fetching requests from the web server and
>> pausing the worker to wait for new requests (in FrankenPHP, we use
>> GoRoutines for this, in Rust or C, other primitives will have to be used),
>> but almost everything else could be shared.
>>
>> For reference, here's the FrankenPHP code I propose to integrate into
>> libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>>
>> The public API is documented here:
>> https://frankenphp.dev/docs/worker/#custom-apps
>>
>> I'd like to hear what the community thinks about this. Would you be
>> interested in this functionality in PHP? Should I work on an RFC?
>>
>> If there's interest, I can work on a patch.
>>
>> Cheers,
>> --
>> Kévin Dunglas
>>
>
> Much like Larry, I'm curious what sort of scope you imagine for this. Are
> you imagining something that is geared specifically towards HTTP requests,
> or would this be a more generic "PHP Application Worker" that might be
> spawned to handle other types of applications? Could we have a worker
> listen to a specific port and respond to or handle all requests on that
> port/device?
>
> Jordan
>

Ho Jordan,

Yes, the scope I imagine is geared specifically towards HTTP requests.
Something more generic than common primitives for SAPIs and a shared public
API to handle HTTP requests with a long-running PHP worker script will be
hard to do outside of SAPIs because they depend on a lot of external
concerns such as the programming language the SAPI is using.


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Kévin Dunglas
On Sun, Dec 24, 2023 at 4:21 PM Larry Garfield 
wrote:

In practice, I want to understand the implications for user-space code.
> Does this mean FPM could be configured in a way to execute a file like that
> shown in the docs page above?  Or would it only work with third party SAPIs
> like FrankenPHP?


In theory, PHP-FPM and the Apache module could - like all other SAPIs - be
enhanced to add a worker mode operating as described in the FrankenPHP doc
thanks to these new primitives.

However, I suggest doing this as a second step, because as described in my
first post, it will still be the responsibility of each SAPI to manage
long-running processes and communication with them. This is simple to do
with Go's GoRoutine and Rust's asynchronous runtimes such as Tokio, it's
definitely more difficult in cross-platform C. I suggest starting by adding
the primitives to libphp, then we'll see how to exploit them (and whether
it's worthwhile) in the built-in SAPIs.
I personally have less interest in working on FPM/CGI/mod_php as the other
possibilities offered by modern SAPIs like FrankenPHP are more important
(better deployment experience as you have a single static binary or Docker
image, Early Hints support, high-quality native HTTP/3 server etc), but I'd
be happy to help if anyone wants to update these SAPIs.

I assume the handler function would be differently named.


I suggest naming the function handle_request() or something similar and
using the same name for all SAPIs, so the same worker script will work
everywhere. I'll update FrankenPHP to use the "standard" name.


> Is passing in super-globals the right/best way to handle each request, or
> would it be sensible to have some other abstraction there?  (Whether a
> formal request object a la PSR-7 or something else.)


Passing super-globals is at the same time the most interoperable solution
(it allows using almost all existing PHP libraries in worker mode without
any change to them), and also allows to reuse of the existing C code.
Transforming super-globals in HttpFoundation, PSR-7, or other objects is
straightforward and can entirely be done userland (it's already what the
Symfony Runtime Component and Laravel Octane do), so there is no need to
"bloat" the C code.

Having more high-level data structures to manipulate HTTP messages similar
to HttpFoundation or PSR-7 in the language could be nice (and is in my
opinion needed), but is a separate topic.
If PHP adds a new abstraction for that at some point, it will be easy to
add support for them both in standard and worker mode.


> To what extent would user-space code run this way have to think about
> concurrency, shared memory, persistent SQL connections, etc?  Does it have
> any implications for fiber-using async code?
>

Regarding concurrency, it doesn't change much (it's similar to existing
SAPI). Regarding memory and SQL connections, extra care is required. Memory
leaks (and other kinds of leaks) should be avoided (or workers should
restart from time to time, which is obviously a poorer solution). Libraries
maintaining SQL connections such as Doctrine or Eloquent must ensure that
the connection isn't active.
The good news is that thanks to RoadRunner, Swoole, Laravel Octane, Symfony
Runtime etc... Most popular libraries are already compatible with
long-running processes, and most issues have been fixed.
Some old apps and libraries will probably never be updatable, but that's
not a big issue because this feature will be entirely opt-in.

Fibers work as expected. There is a small limitation when using them with
Go (that is being tracked in the Go runtime,
https://frankenphp.dev/docs/known-issues/#fibers), but it's not related to
the C code of the worker mode, and this limitation shouldn't exist for
SAPIs not written in Go.


> Depending on the details, this could be like fibers but for 3rd party
> SAPIs (something about 4 people in the world actually care about directly,
> everyone else just uses Revolt, Amp, or React, but mostly it doesn't get
> used), or completely changing the way 90% of the market runs PHP, which
> means frameworks will likely adapt to use that model primarily or
> exclusively (ie, less of a need for a "compile" step as a generated
> container or dispatcher is just held in memory automatically already).  The
> latter sounds exciting to me, but I'm not sure which is your intent, so I
> don't know if I'm going too far with it. :-)
>

My intent is that most SAPIs expose the same (or a very similar
interoperable) worker mode. So (I hope) that most PHP developers will not
have to deal with these primitives directly, but that it will allow a new
generation of super-fast PHP apps to be created. Most frameworks already
support that but require a lot of boilerplate code to support the different
existing engines. Standardizing will likely increase adoption and will
allow collaboration to make the low-level code that I propose to move in
libphp as fast, stable, and clean as possible.


> 

Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-24 Thread Jordan LeDoux
On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:

> Hello and Merry Christmas!
>
> One of the main features of FrankenPHP is its worker mode, which lets you
> keep a PHP application in memory to handle multiple HTTP requests.
>
> Worker modes are becoming increasingly popular in the PHP world. Symfony
> (Runtime Component), Laravel (Octane), and many projects based on these
> frameworks (API Platform, Sulu...) now support a worker mode.
>
> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
> engines supporting worker modes.
>
> According to benchmarks, worker modes can improve the performance of PHP
> applications by up to 15 times.
> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
> web server, a new generation of SAPIs is currently under development.
> Several SAPIs written in Rust (including one by the RoadRunner team) are
> currently under development.
>
> These SAPIs, along with existing SAPIs, could benefit from a shared
> infrastructure to build worker modes.
>
>
>
> The FrankenPHP code is written and should be easy to move around in PHP
> itself, to enable other SAPIs to use it.
>
> In addition to sharing code, maintenance, performance optimization, etc.,
> the existence of a common infrastructure would standardize the way worker
> scripts are created and provide a high-level PHP API for writing worker
> scripts that work with all SAPIs that rely on this new feature.
>
> SAPIs will still have to handle fetching requests from the web server and
> pausing the worker to wait for new requests (in FrankenPHP, we use
> GoRoutines for this, in Rust or C, other primitives will have to be used),
> but almost everything else could be shared.
>
> For reference, here's the FrankenPHP code I propose to integrate into
> libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>
> The public API is documented here:
> https://frankenphp.dev/docs/worker/#custom-apps
>
> I'd like to hear what the community thinks about this. Would you be
> interested in this functionality in PHP? Should I work on an RFC?
>
> If there's interest, I can work on a patch.
>
> Cheers,
> --
> Kévin Dunglas
>

Much like Larry, I'm curious what sort of scope you imagine for this. Are
you imagining something that is geared specifically towards HTTP requests,
or would this be a more generic "PHP Application Worker" that might be
spawned to handle other types of applications? Could we have a worker
listen to a specific port and respond to or handle all requests on that
port/device?

Jordan


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-24 Thread Larry Garfield
On Sat, Dec 23, 2023, at 2:34 PM, Kévin Dunglas wrote:
> Hello and Merry Christmas!
>
> One of the main features of FrankenPHP is its worker mode, which lets you
> keep a PHP application in memory to handle multiple HTTP requests.
>
> Worker modes are becoming increasingly popular in the PHP world. Symfony
> (Runtime Component), Laravel (Octane), and many projects based on these
> frameworks (API Platform, Sulu...) now support a worker mode.
>
> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
> engines supporting worker modes.
>
> According to benchmarks, worker modes can improve the performance of PHP
> applications by up to 15 times.
> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
> web server, a new generation of SAPIs is currently under development.
> Several SAPIs written in Rust (including one by the RoadRunner team) are
> currently under development.
>
> These SAPIs, along with existing SAPIs, could benefit from a shared
> infrastructure to build worker modes.
>
>
>
> The FrankenPHP code is written and should be easy to move around in PHP
> itself, to enable other SAPIs to use it.
>
> In addition to sharing code, maintenance, performance optimization, etc.,
> the existence of a common infrastructure would standardize the way worker
> scripts are created and provide a high-level PHP API for writing worker
> scripts that work with all SAPIs that rely on this new feature.
>
> SAPIs will still have to handle fetching requests from the web server and
> pausing the worker to wait for new requests (in FrankenPHP, we use
> GoRoutines for this, in Rust or C, other primitives will have to be used),
> but almost everything else could be shared.
>
> For reference, here's the FrankenPHP code I propose to integrate into
> libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>
> The public API is documented here:
> https://frankenphp.dev/docs/worker/#custom-apps
>
> I'd like to hear what the community thinks about this. Would you be
> interested in this functionality in PHP? Should I work on an RFC?
>
> If there's interest, I can work on a patch.
>
> Cheers,

In concept, I love this and would be ecstatic to see it happen.

In practice, I want to understand the implications for user-space code.  Does 
this mean FPM could be configured in a way to execute a file like that shown in 
the docs page above?  Or would it only work with third party SAPIs like 
FrankenPHP?  I assume the handler function would be differently named.  Is 
passing in super-globals the right/best way to handle each request, or would it 
be sensible to have some other abstraction there?  (Whether a formal request 
object a la PSR-7 or something else.)  To what extent would user-space code run 
this way have to think about concurrency, shared memory, persistent SQL 
connections, etc?  Does it have any implications for fiber-using async code?

Depending on the details, this could be like fibers but for 3rd party SAPIs 
(something about 4 people in the world actually care about directly, everyone 
else just uses Revolt, Amp, or React, but mostly it doesn't get used), or 
completely changing the way 90% of the market runs PHP, which means frameworks 
will likely adapt to use that model primarily or exclusively (ie, less of a 
need for a "compile" step as a generated container or dispatcher is just held 
in memory automatically already).  The latter sounds exciting to me, but I'm 
not sure which is your intent, so I don't know if I'm going too far with it. :-)

Please advise on what the implications would be for the non-SAPI-developing PHP 
devs out there.

--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-23 Thread Kévin Dunglas
Hello and Merry Christmas!

One of the main features of FrankenPHP is its worker mode, which lets you
keep a PHP application in memory to handle multiple HTTP requests.

Worker modes are becoming increasingly popular in the PHP world. Symfony
(Runtime Component), Laravel (Octane), and many projects based on these
frameworks (API Platform, Sulu...) now support a worker mode.

In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
engines supporting worker modes.

According to benchmarks, worker modes can improve the performance of PHP
applications by up to 15 times.
In addition to FrankenPHP, which is basically a SAPI for Go's integrated
web server, a new generation of SAPIs is currently under development.
Several SAPIs written in Rust (including one by the RoadRunner team) are
currently under development.

These SAPIs, along with existing SAPIs, could benefit from a shared
infrastructure to build worker modes.



The FrankenPHP code is written and should be easy to move around in PHP
itself, to enable other SAPIs to use it.

In addition to sharing code, maintenance, performance optimization, etc.,
the existence of a common infrastructure would standardize the way worker
scripts are created and provide a high-level PHP API for writing worker
scripts that work with all SAPIs that rely on this new feature.

SAPIs will still have to handle fetching requests from the web server and
pausing the worker to wait for new requests (in FrankenPHP, we use
GoRoutines for this, in Rust or C, other primitives will have to be used),
but almost everything else could be shared.

For reference, here's the FrankenPHP code I propose to integrate into
libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245

The public API is documented here:
https://frankenphp.dev/docs/worker/#custom-apps

I'd like to hear what the community thinks about this. Would you be
interested in this functionality in PHP? Should I work on an RFC?

If there's interest, I can work on a patch.

Cheers,
-- 
Kévin Dunglas