HTTP/2 is entirely outside the scope of the PHP web SAPI as it currently
exists. The protocol impacts the actual HTTP server and has nothing to do
with the SAPI runtime which is simply handed information about the HTTP
request once the server parses it. The protocol used to communicate those
details between the client and the HTTP server does not concern the web
SAPI. There is no need for any sort of "support for h2" in PHP; it's the
web server's concern. Apache and nginx will add support for h2 and PHP will
continue working as it always has.
That said, the php web SAPI derives exceedingly little benefit from the
advent of HTTP/2.0. h2 is designed to allow multiplexing of many requests
over the same TCP connection but the PHP web SAPI still has the same
bottleneck it had before h2: one thread/process per request.
As for websockets, you can do that using the web SAPI right now if you
wished but this would be inadvisable because long-lived connections will
quickly fill the bottleneck in every PHP web application (concurrent
threads/processes for each "request").
Instead, the appropriate solution for websockets would be to implement a
socket server directly in the CLI that speaks the websocket protocol.
Would it be useful to have raw incremental parsing functionality for
HTTP/1.1, HTTP/1.2 and websocket protocols available in userland? Sure, but
this falls more in the realm of an extension than anything else as few
people are implementing full-blown http and websocket servers in the CLI
right now.
Le 31/03/2015 15:56, Daniel Lowrey a écrit :
HTTP/2 is entirely outside the scope of the PHP web SAPI as it currently
exists. The protocol impacts the actual HTTP server and has nothing to do
with the SAPI runtime which is simply handed information about the HTTP
request once the server parses it. The protocol used to communicate those
details between the client and the HTTP server does not concern the web
SAPI. There is no need for any sort of "support for h2" in PHP; it's the
web server's concern. Apache and nginx will add support for h2 and PHP will
continue working as it always has.That said, the php web SAPI derives exceedingly little benefit from the
advent of HTTP/2.0. h2 is designed to allow multiplexing of many requests
over the same TCP connection but the PHP web SAPI still has the same
bottleneck it had before h2: one thread/process per request.As for websockets, you can do that using the web SAPI right now if you
wished but this would be inadvisable because long-lived connections will
quickly fill the bottleneck in every PHP web application (concurrent
threads/processes for each "request").Instead, the appropriate solution for websockets would be to implement a
socket server directly in the CLI that speaks the websocket protocol.Would it be useful to have raw incremental parsing functionality for
HTTP/1.1, HTTP/1.2 and websocket protocols available in userland? Sure, but
this falls more in the realm of an extension than anything else as few
people are implementing full-blown http and websocket servers in the CLI
right now.
Hi Daniel,
Your message is focusing on the solution I can find today in the wild,
not about the need mys previous message was about, namely multiplexing
and message push.
Anyway I'm aware of this and I understand your point, but why should'nt
we be able, natively, to exploit HTTP/2 enhancements, particurlarly
resources multiplexing and data push?
Why woud we restrain to exploit 20 years old protocol features,
deliberately omitting new ones that are already implemented on other
platforms?
Grégory
Le 31/03/2015 15:56, Daniel Lowrey a écrit :
HTTP/2 is entirely outside the scope of the PHP web SAPI as it currently
exists. The protocol impacts the actual HTTP server and has nothing to do
with the SAPI runtime which is simply handed information about the HTTP
request once the server parses it. The protocol used to communicate those
details between the client and the HTTP server does not concern the web
SAPI. There is no need for any sort of "support for h2" in PHP; it's the
web server's concern. Apache and nginx will add support for h2 and PHP
will
continue working as it always has.That said, the php web SAPI derives exceedingly little benefit from the
advent of HTTP/2.0. h2 is designed to allow multiplexing of many requests
over the same TCP connection but the PHP web SAPI still has the same
bottleneck it had before h2: one thread/process per request.As for websockets, you can do that using the web SAPI right now if you
wished but this would be inadvisable because long-lived connections will
quickly fill the bottleneck in every PHP web application (concurrent
threads/processes for each "request").Instead, the appropriate solution for websockets would be to implement a
socket server directly in the CLI that speaks the websocket protocol.Would it be useful to have raw incremental parsing functionality for
HTTP/1.1, HTTP/1.2 and websocket protocols available in userland? Sure,
but
this falls more in the realm of an extension than anything else as few
people are implementing full-blown http and websocket servers in the CLI
right now.Hi Daniel,
Your message is focusing on the solution I can find today in the wild,
not about the need mys previous message was about, namely multiplexing
and message push.Anyway I'm aware of this and I understand your point, but why should'nt
we be able, natively, to exploit HTTP/2 enhancements, particurlarly
resources multiplexing and data push?Why woud we restrain to exploit 20 years old protocol features,
deliberately omitting new ones that are already implemented on other
platforms?Grégory
You're right -- I was addressing the status quo.
The issue here is this: the web SAPI is historically the most stable thing
about PHP. Supporting things like message push and multiplexing would
require a fundamental change in what the web SAPI is. You would have to
junk the entire model and create something completely new. It wouldn't be
PHP anymore because you couldn't use the thread/process per-request model;
users could no longer rely on the ease and simplicity of every function
call being a simple synchronous operation.
This kind of major paradigm shift is something that couldn't remotely be
considered for PHP7. Even if it were possible you have to consider the web
SAPI's target demographic. This demographic knows nothing about
non-blocking IO and multitasking.
I used to be a proponent of integrating things like this directly into the
core of PHP. However I no longer consider this to be a good idea. Why?
Because all of the functionality needed to implement these things yourself
is available in extensions right now. I've personally worked on a
closed-source userland non-blocking HTTP+websocket server over the last
couple of years that clears 80,000 requests per second with 10,000
simultaneous clients running PHP7 on a single box with an i2600K cpu.
Instead of massively changing the fundamental nature of the PHP web SAPI I
believe we should focus on improving PHP as a language and not a web
framework. By doing so we make it increasingly possible to implement things
like this directly in userland with good performance. This can be
accomplished right now by simply focusing on extension development (like
php-uv which you mentioned and I've contributed to myself).
Would I personally prefer to re-implement everything in PHP on top of libuv
and bake non-blocking and threaded concurrency directly into the language
with async functions and promises? Absolutely. But you're talking about a
massive amount of work here. In standard internet parlance ... ain't no one
got time for that.
Hi,
Le 31/03/2015 15:56, Daniel Lowrey a écrit :
HTTP/2 is entirely outside the scope of the PHP web SAPI as it currently
exists. The protocol impacts the actual HTTP server and has nothing to do
with the SAPI runtime which is simply handed information about the HTTP
request once the server parses it. The protocol used to communicate those
details between the client and the HTTP server does not concern the web
SAPI. There is no need for any sort of "support for h2" in PHP; it's the
web server's concern. Apache and nginx will add support for h2 and PHP
will
continue working as it always has.That said, the php web SAPI derives exceedingly little benefit from the
advent of HTTP/2.0. h2 is designed to allow multiplexing of many requests
over the same TCP connection but the PHP web SAPI still has the same
bottleneck it had before h2: one thread/process per request.As for websockets, you can do that using the web SAPI right now if you
wished but this would be inadvisable because long-lived connections will
quickly fill the bottleneck in every PHP web application (concurrent
threads/processes for each "request").Instead, the appropriate solution for websockets would be to implement a
socket server directly in the CLI that speaks the websocket protocol.Would it be useful to have raw incremental parsing functionality for
HTTP/1.1, HTTP/1.2 and websocket protocols available in userland? Sure,
but
this falls more in the realm of an extension than anything else as few
people are implementing full-blown http and websocket servers in the CLI
right now.Hi Daniel,
Your message is focusing on the solution I can find today in the wild,
not about the need mys previous message was about, namely multiplexing
and message push.Anyway I'm aware of this and I understand your point, but why should'nt
we be able, natively, to exploit HTTP/2 enhancements, particurlarly
resources multiplexing and data push?Why woud we restrain to exploit 20 years old protocol features,
deliberately omitting new ones that are already implemented on other
platforms?Grégory
You're right -- I was addressing the status quo.
The issue here is this: the web SAPI is historically the most stable thing
about PHP. Supporting things like message push and multiplexing would
require a fundamental change in what the web SAPI is. You would have to
junk the entire model and create something completely new. It wouldn't be
PHP anymore because you couldn't use the thread/process per-request model;
users could no longer rely on the ease and simplicity of every function
call being a simple synchronous operation.
this ain't exactly true. Currently in MT environment the task of data
separation is pushed to the TSRM by using TLS. Now, if TSRM is
reimplemented in a fashion that the data is not stored by using TLS but
other mechanism and cooperative multitasking is not something that can't
be done. The truth is that userland is isolated from the process data
space so for it it won't make a difference. It's just that using threads
for separation is the easiest thing (after process per script).
The good thing is that TSRM is an abstraction for its clients.
This kind of major paradigm shift is something that couldn't remotely be
considered for PHP7. Even if it were possible you have to consider the web
SAPI's target demographic. This demographic knows nothing about
non-blocking IO and multitasking.I used to be a proponent of integrating things like this directly into the
core of PHP. However I no longer consider this to be a good idea. Why?
Because all of the functionality needed to implement these things yourself
is available in extensions right now. I've personally worked on a
closed-source userland non-blocking HTTP+websocket server over the last
couple of years that clears 80,000 requests per second with 10,000
simultaneous clients running PHP7 on a single box with an i2600K cpu.Instead of massively changing the fundamental nature of the PHP web SAPI I
believe we should focus on improving PHP as a language and not a web
framework. By doing so we make it increasingly possible to implement things
like this directly in userland with good performance. This can be
accomplished right now by simply focusing on extension development (like
php-uv which you mentioned and I've contributed to myself).Would I personally prefer to re-implement everything in PHP on top of libuv
and bake non-blocking and threaded concurrency directly into the language
with async functions and promises? Absolutely. But you're talking about a
massive amount of work here. In standard internet parlance ... ain't no one
got time for that.
Best,
Andrey
Andrey Hristov wrote on 31/03/2015 16:02:
Currently in MT environment the task of data separation is pushed to
the TSRM by using TLS. Now, if TSRM is reimplemented in a fashion that
the data is not stored by using TLS but other mechanism and
cooperative multitasking is not something that can't be done. The
truth is that userland is isolated from the process data space so for
it it won't make a difference. It's just that using threads for
separation is the easiest thing (after process per script).
The good thing is that TSRM is an abstraction for its clients.
Isn't the point that to get a real advantage from these technologies,
the userland needs to be aware of threads / events? That's what
requires a fundamental rethink of the language.
TSRM/TLS allows you to drop from one-process-per-request to
one-thread-per-request, but it doesn't save you the expense of
repeatedly building up and tearing down an execution environment.
Regards,
Rowan Collins
[IMSoP]
Andrey Hristov wrote on 31/03/2015 16:02:
Currently in MT environment the task of data separation is pushed to
the TSRM by using TLS. Now, if TSRM is reimplemented in a fashion that
the data is not stored by using TLS but other mechanism and
cooperative multitasking is not something that can't be done. The
truth is that userland is isolated from the process data space so for
it it won't make a difference. It's just that using threads for
separation is the easiest thing (after process per script).
The good thing is that TSRM is an abstraction for its clients.Isn't the point that to get a real advantage from these technologies,
the userland needs to be aware of threads / events? That's what
requires a fundamental rethink of the language.
No, actually it doesn't need threads. There is no need to introduce
threads. Threads are for coarsely grained tasks. It is overkill to start
and finish threads in this environment. It is not overkill to have pool
of threads that can execute simple tasks.
PHP doesn't have this problem - the need for threads. PHP's problem are
all the blocking APIs, including the ones I have worked on and created
myself. PHP needs non-blockable APIs + a notion of coroutines +
promises. How the coroutines are scheduled is not important (whether in
the same thread, on thread pool, even in another process). Directly
sharing data should not be possible, only serialized input/output.
TSRM/TLS allows you to drop from one-process-per-request to
one-thread-per-request, but it doesn't save you the expense of
repeatedly building up and tearing down an execution environment.
So, if Zend can be optimized to quickly clean the execution environment,
and easily switch between them, we can have a giant leap towards
concurrent non-blockable PHP. The idea is simple - the Zend environment
should be some structure, and TSRM needs implementation not using TLS,
in this case. The MySQL Server used to bind a connection to a thread but
since years these are decoupled and with the right plugin you can have
100 threads serving many times more connections because thread switching
is an expensive task. This ain't rocket science.
Regards,
Best,
Andrey
So, if Zend can be optimized to quickly clean the execution
environment,
and easily switch between them, we can have a giant leap towards
concurrent non-blockable PHP. The idea is simple - the Zend environmentshould be some structure, and TSRM needs implementation not using TLS,
in this case. The MySQL Server used to bind a connection to a thread
but
since years these are decoupled and with the right plugin you can have
100 threads serving many times more connections because thread
switching
is an expensive task. This ain't rocket science.
You make it sound so simple, but the fact that an environment is set up and torn down for each request is fundamental to the whole language, not just a detail of the engine.
If all you're doing is making that setup and teardown quicker, I don't see how you're getting any closer to asynchronous code. FPM could do all sorts of magic with its memory management, but it wouldn't help someone write a WebSocket server.
Maybe I'm missing something, but I can't picture how you'd have a meaningfully event-based SAPI that looked just like a single-request one to the user.
Regards,
Rowan Collins
[IMSoP]
So, if Zend can be optimized to quickly clean the execution
environment,
and easily switch between them, we can have a giant leap towards
concurrent non-blockable PHP. The idea is simple - the Zend environmentshould be some structure, and TSRM needs implementation not using TLS,
in this case. The MySQL Server used to bind a connection to a thread
but
since years these are decoupled and with the right plugin you can have
100 threads serving many times more connections because thread
switching
is an expensive task. This ain't rocket science.You make it sound so simple, but the fact that an environment is set up and torn down for each request is fundamental to the whole language, not just a detail of the engine.
If all you're doing is making that setup and teardown quicker, I don't see how you're getting any closer to asynchronous code. FPM could do all sorts of magic with its memory management, but it wouldn't help someone write a WebSocket server.
being able to serve more than 1 request in a thread by not using TLS
allows you to lower the number of threads used, significantly. On top of
that by adding coroutines which run on a thread pool with fast setup and
teardown give you the notion of parallel execution and because data is
exchanged with the coroutines only in serialized way, not by sharing it,
a bunch of problems related to concurrency won't happen. Add promises to
this soup together with non-blocking APIs (this won't happen overnight)
and everything fits.
Maybe I'm missing something, but I can't picture how you'd have a meaningfully event-based SAPI that looked just like a single-request one to the user.
I don't think that the SAPI needs to change. The SAPI doesn't mandate
processes, threads or whatever else primitives. It's a way to
(de)initialize module/request.
Regards,
Best,
Andrey
Le 31/03/2015 23:47, Andrey Hristov a écrit :
On 31 March 2015 21:23:56 GMT+01:00, Andrey Hristov php@hristov.com
wrote:So, if Zend can be optimized to quickly clean the execution
environment,
and easily switch between them, we can have a giant leap towards
concurrent non-blockable PHP. The idea is simple - the Zend environmentshould be some structure, and TSRM needs implementation not using TLS,
in this case. The MySQL Server used to bind a connection to a thread
but
since years these are decoupled and with the right plugin you can have
100 threads serving many times more connections because thread
switching
is an expensive task. This ain't rocket science.You make it sound so simple, but the fact that an environment is set
up and torn down for each request is fundamental to the whole
language, not just a detail of the engine.If all you're doing is making that setup and teardown quicker, I don't
see how you're getting any closer to asynchronous code. FPM could do
all sorts of magic with its memory management, but it wouldn't help
someone write a WebSocket server.being able to serve more than 1 request in a thread by not using TLS
allows you to lower the number of threads used, significantly. On top of
that by adding coroutines which run on a thread pool with fast setup and
teardown give you the notion of parallel execution and because data is
exchanged with the coroutines only in serialized way, not by sharing it,
a bunch of problems related to concurrency won't happen. Add promises to
this soup together with non-blocking APIs (this won't happen overnight)
and everything fits.Maybe I'm missing something, but I can't picture how you'd have a
meaningfully event-based SAPI that looked just like a single-request
one to the user.I don't think that the SAPI needs to change. The SAPI doesn't mandate
processes, threads or whatever else primitives. It's a way to
(de)initialize module/request.Regards,
Best,
Andrey
Hi Andrey,
So, if I understand your point, there could be a way to implement a SAPI
without TSRM (or a limited set)?
Grégory Planchat
On 31 March 2015 21:23:56 GMT+01:00, Andrey Hristov php@hristov.com
wrote:So, if Zend can be optimized to quickly clean the execution
environment,
and easily switch between them, we can have a giant leap towards
concurrent non-blockable PHP. The idea is simple - the Zend
environmentshould be some structure, and TSRM needs implementation not using
TLS,
in this case. The MySQL Server used to bind a connection to a thread
but
since years these are decoupled and with the right plugin you can
have
100 threads serving many times more connections because thread
switching
is an expensive task. This ain't rocket science.You make it sound so simple, but the fact that an environment is set
up and torn down for each request is fundamental to the whole language,
not just a detail of the engine.If all you're doing is making that setup and teardown quicker, I
don't see how you're getting any closer to asynchronous code. FPM could
do all sorts of magic with its memory management, but it wouldn't help
someone write a WebSocket server.being able to serve more than 1 request in a thread by not using TLS
allows you to lower the number of threads used, significantly. On top
of
that by adding coroutines which run on a thread pool with fast setup
and
teardown give you the notion of parallel execution and because data is
exchanged with the coroutines only in serialized way, not by sharing
it,
a bunch of problems related to concurrency won't happen. Add promises
to
this soup together with non-blocking APIs (this won't happen overnight)and everything fits.
Maybe I'm missing something, but I can't picture how you'd have a
meaningfully event-based SAPI that looked just like a single-request
one to the user.I don't think that the SAPI needs to change. The SAPI doesn't mandate
processes, threads or whatever else primitives. It's a way to
(de)initialize module/request.
The SAPI needs to change to have coroutines as something that can be allocated on an arbitrary thread pool. PHP contains a lot of things which imply global state (I came up with a list in a previous thread) and those are what I mean by setup and teardown. However fast you make them, they have to happen exactly once per userland script execution.
In an event-based environment, you either have to not use any such global state (which makes for a very different language), or it has to be shared between all your lightweight workers, in which case those workers can see each other at the userland level.
You can implement this in userland right now, using the CLI SAPI as the container of global state, and a co-operative multi-tasking scheduler built with clever use of "yield". A scalable and efficient version of that would be a new SAPI, and would have to make some tough choices about how existing features behaved, or if they were allowed at all.
Regards,
Rowan Collins
[IMSoP]
Le 31/03/2015 16:40, Daniel Lowrey a écrit :
The issue here is this: the web SAPI is historically the most stable thing
about PHP. Supporting things like message push and multiplexing would
require a fundamental change in what the web SAPI is. You would have to
junk the entire model and create something completely new. It wouldn't be
PHP anymore because you couldn't use the thread/process per-request model;
users could no longer rely on the ease and simplicity of every function
call being a simple synchronous operation.
This kind of major paradigm shift is something that couldn't remotely be
considered for PHP7. Even if it were possible you have to consider the web
SAPI's target demographic. This demographic knows nothing about
non-blocking IO and multitasking.
I'm not saying that we should drop the current web SAPIs to the ground,
I'm just advancing the idea of enhancing it or find some other way - in
parallel of existing SAPIs - to bring these functionalities, maybe a
specific SAPI.
CLI SAPI is already using an unique RINIT/RSHUTDOWN cycle, programs such
as ReactPHP or the one I built with php-uv -and probably the one you
mentioned building yourself- suffers from brutal crashes on fatal errors
and does not take benefit from the request isolation. These issues will
be indirectly and partially addessed with the ZE now sending exceptions
instead of E_ERROR.
Now, about asynchronous operations, PHP developers are also often
Javascript developers, may it be front end or back end on Node. Lots of
them are used to asynchronous calls, others will simply learn to be used
to it or continue to use the current synchronous functionalities and
SAPIs, I see this as an opt-in.
Lots of PHP developers don't know what is a process or a thread and
doesn't feel the need to dig the subject and I'm perfectly ok with that,
each project finds his own needs and solutions. That said, then why
should concerned developers suffer from missing functionalities?
I used to be a proponent of integrating things like this directly into the
core of PHP. However I no longer consider this to be a good idea. Why?
Because all of the functionality needed to implement these things yourself
is available in extensions right now. I've personally worked on a
closed-source userland non-blocking HTTP+websocket server over the last
couple of years that clears 80,000 requests per second with 10,000
simultaneous clients running PHP7 on a single box with an i2600K cpu.
Is this server running with php-uv?
The issue here is that there is no simple and uniform way to implement
it. Agree with me or not, it is clearly reserved to a small part of
seasoned PHP developers, used to concurrent programming, extension
writing/compilation and asynchronous development.
It is a border-line way of developing with PHP, not portable at all as
long as php-uv isn't available anywhere but on your own dedicated server
(if your SysOP even accepts to install a considered self-maintained and
possibly vulnerable extension).
Instead of massively changing the fundamental nature of the PHP web SAPI I
believe we should focus on improving PHP as a language and not a web
framework. By doing so we make it increasingly possible to implement things
like this directly in userland with good performance. This can be
accomplished right now by simply focusing on extension development (like
php-uv which you mentioned and I've contributed to myself).
I'm just bringing some ideas here, as long as I'm not a php-src
developer. I know some notions but I don't have the distance required to
find -by myself- the best solutions.
Yes php-uv is a great tool, but still incomplete (and IMO missing an OOP
API).
Would I personally prefer to re-implement everything in PHP on top of libuv
and bake non-blocking and threaded concurrency directly into the language
with async functions and promises? Absolutely. But you're talking about a
massive amount of work here. In standard internet parlance ... ain't no one
got time for that.
I can't tell if the existing stream API can integrate libuv I/O
handling, especially async ones. I figured out that it was nearly
impossible to integrate php-uv in an userland streamWrapper.
Now, that said and to come back to the main subject, HTTP/2 is coming
now in production on large scale websites and will be present in a
large amount of web traffic in the next couple of years. PHP can't
afford to miss the boat or to force each developer reimplement his own
protocol layer.
Possible solutions would be :
-
About multiplexing :
1.a. integrate php-uv in the core in its current form and let
developers implement their own protocol layer
1.b. transform some project like ReactPHP into an extension (using
Zephir and/or native C)
1.c. create a new SAPI or extend an existing one, which woud offer
the possibility of manipulating the resource multiplexing queue. PHP
would still be in the Apache2/CGI stack, but would notify the server to
send a resource list -
About push: same as 1.a. and 1.b.
Grégory
Am 31.03.2015 um 19:09 schrieb Grégory Planchat:
Possible solutions would be :
- About multiplexing :
1.a. integrate php-uv in the core in its current form and let
developers implement their own protocol layer
1.b. transform some project like ReactPHP into an extension (using
Zephir and/or native C)
1.c. create a new SAPI or extend an existing one, which woud offer the
possibility of manipulating the resource multiplexing queue. PHP would
still be in the Apache2/CGI stack, but would notify the server to send a
resource list
I really don't see what action there is to take for PHP with regards to
multiplexing.
Currently, Apache seems not to support HTTP/2, other servers I don't
know. But when Apache will support HTTP/2, multiplexing will most likely
work similar to how it worked with SPDY (the predecessor to HTTP/2).
You just send an additional header containing the files you want the
server to provide to the client. mod_spdy used the
X-Associated-Content-Header (see
https://code.google.com/p/mod-spdy/wiki/OptimizingForSpdy)
"More" multiplexing will mean multiple parallel execution paths within
the engine but that kind of parallelism introduces a hell of concurrency
problems nobody truly wants.
- About push: same as 1.a. and 1.b.
Push can only work with long running PHP processes. I kind of agree a
stable PHP daemon process mode/SAPI would be nice. That mode would be
similar to a WebSockets mode which we should get in the future. But that
has nothing to do with HTTP/2 from my perspective.
Greets
Dennis