
Asynchronous PHP: Why? - kiyanwang
http://sergeyzhuk.me/2018/02/02/why-asynchronous-php/
======
phs2501
IMHO, the biggest reason to use a language like Node when you want to do async
programming is that for any random library you choose there's a 98% chance
that it properly supports async as well and won't block on you. For better or
worse async is pervasive in the ecosystem. Even in good languages like Python
that have (allegedly; I've not used them) good async frameworks, most
libraries will block as it's the normal I/O mode for the language, which
really limits what you can use. I can't imagine the situation will be any
better in PHP.

~~~
whopa
People keep saying that Node is async native, but the GC is global and
synchronous, and that property will bite you on availability even at moderate
traffic, i.e. sooner than you'd expect.

------
laurencei
I am an experienced PHP developer - and I also ask the question "why
asynchronous PHP" all the time - except in a different context.

Every time I start thinking about doing some strange magic "asynchronous"
function - I realise I can just use the standard queue systems built into most
frameworks today. i.e. get the task - push it onto a queue - then do something
else without waiting for the queue itself.

The thought of dealing with "forked" processes, memory leaks, strange race
conditions etc and all the stuff that comes with async PHP does not seem worth
it. It is very easy to "reason" logic behind a queue system. I can test it
extremely well, and essentially break the process up into sub sections and not
have to worry.

Note - I'm not saying there is no place for true asynchronous functions - but
I think people reach for them in PHP when other easier solutions might suffice
in the first place.

~~~
meritt
One example that I think fits very well is a websocket server. As you often
have a large number of clients with long-running connections and relatively
low-volume bidirectional communication, a single process running react/amp can
easily handle hundreds or thousands of clients.

The majority of the examples out there are indeed contrived and better suited
to a queue system as you've described.

~~~
francislavoie
+1 to this. I like Ratchet for websockets written in PHP. One nice thing is
that I can share certain things like session code between my websocket server
and my backend framework. Having both be in the same language, in the same
project, makes things a lot cleaner for me.

------
scribu
> When you already have a solid background in PHP, it will be much easier for
> you just to dig in some libraries and tools for your use-case, instead of
> learning a new language and a new ecosystem.

The main challenge when going async isn’t learning new syntax. It’s dealing
with non-linear flow control and with different abstractions.

So, I remain unconvinced that picking PHP’s comparatively obscure async
ecosystem is a good longterm strategy.

~~~
chriswarbo
This sounds very plausible to me. As well as PHP, I've written a bunch of Java
and threaded Java. I treat the latter two as different languages: yes you can
use the same parser for both, but _adding_ threads to the semantics also
_removes_ a lot of the mental models and assumptions we could previously make.

------
tcd
tl;dr for the most useless article I've ever read. See links:

[https://amphp.org/](https://amphp.org/)
[https://reactphp.org/](https://reactphp.org/)

Was basically the article. r/savedyouaclick

------
jaequery
Elixir has gotten this down perfectly.

I always wished js was sync by default and only async when you tell it to. Now
you have the words async/await (and not too long ago promises, bluebird,
waterfall), spread out all over your code for that since you only need async
perhaps less than a quarter of your code base. but i dont see js ever becoming
procedural first anytime soon.

then I discovered Elixir, i was curious to see how they tout their highly
concurrent functional language solved this issue. and surprisingly its as
simple as wrapping a block of code inside an async block. its such a pleasant
experience finally having best of both worlds, especially coming from years of
callback hells and trying to debug what becomes a set of spaghetti code for
performing simple things.

~~~
romanovcode
> I always wished js was sync by default

`let res = await someAsyncOperation();`

~~~
jaequery
so, i was hoping for not even having to type in async/await and make this
possible: let res = someAsyncOperation()

and whenever you want an async operation (non-blocking), thats when you do
something like:

async { let res = someAsyncOperation() }

~~~
always_good
I'm not sure what that's supposed to solve since you want to handle
error/results at that top-level `async` in your example.

For example, in Javascript, you would often just have a top-level async
function and stay inside async world the whole time.

Putting your example in the middle of some random code can already be done by
calling a promise but not putting the downstream code inside its .then()
block.

One of the nicest things about Javascript is the absolute simplicity of its
concurrency model, one of those perks coming from its single-threaded nature.
I look at something like C# and Kotlin with their BYO await semantics as
something I'm glad Javascript doesn't have.

------
nkcmr
just use [hack]([https://hhvm.com/](https://hhvm.com/)).

hack has language-level support for async tasks[^1]. and is 99% compatible
with PHP.

On the other hand, I _would_ love to see PHP8 bring language-level support for
async tasks.

[^1]:
[https://docs.hhvm.com/hack/async/introduction](https://docs.hhvm.com/hack/async/introduction)

~~~
pbalau
I think you are missunderstanding this a bit, hack has async io.

If you have only 1 external system that both indexes the data and stores it,
this won't help you that much.

But if you have an indexing system and another, with many read slaves, that
stores the data, then async will help you.

You will do 1 external io request to retrieve a list of ids/identifiers then
as many replicas paralel requests to retrieve and format the data.

------
ars
I tried to do this. Limited to the context of database queries. Run them
asynchronously, and pick up the results later.

It works with MySQL, it doesn't with PostgreSQL. PostgreSQL has options for
asynchronous queries, but it's clear than even the person who made them has
never actually used them!

Take a look at the docs for pg_send_query: "multiple queries cannot be sent
over a busy connection. If a query is sent while the connection is busy, it
waits until the last query is finished and discards all its results."

If you actually try, it will block on the next query! Who wrote this useless
library?

There is also no callback or anything, you simply have to allow it to block in
order to pick up results. (There is the undocumented pg_select which might
work.) Queries must be sent and received in order, and one at a time. You
can't run 2 at once (say a long running query, then a quick short one later in
your code). You can't even send another one while the first is running (and
block), because that causes the results from the first to be discarded.

Very disappointed with PostgreSQL because of this.

In contrast MySQL has mysqli_poll() which actually works like you'd expect.

If I had a job that needed asynchronous database queries, I'd definitely pick
MySQL.

~~~
phs2501
Make multiple connections to the database. A transaction is at the "scope" of
a connection anyway, and I don't think there are any useful semantics for
multiple SQL statements being executed in parallel in a single transaction
anyway, so it's likely Postgres is trying to save you from yourself here.

I'll agree that the PHP Postgres API appears to be very low-level, and the
fact that it does not offer callback support may be due to the fact that PHP
doesn't have a standard event loop to plug into. There may be higher-level
libraries that do better here. (I don't know much about PHP.) Postgres is
perfectly usable in an async manner from other languages, however.

------
EGreg
_Of course, when PHP was created its goal was not to be a programming language
that can be used to build large complicated applications. When it happened
there was no JavaScript and no asynchronous stuff in mind._

I just came here to say that ... neither was Javascript :)

------
osrec
On the topic of asynchronous PHP, swoole ([https://github.com/swoole/swoole-
src](https://github.com/swoole/swoole-src)) is very interesting. Lacks
documentation at the moment, but outperformed Node on a variety of tests I
tried with MySQL.

------
Piskvorrr
"Asynchronous PHP; Why? Because it's there." I was expecting some actual
reason.

------
jameshilliard
I know a decent amount of php, but I'm primarily a Python developer who writes
most code with asyncio and twisted.

I tried doing a relatively trivial async php script(basically a script that
was supposed to make an outbound redis pubsub connection and outbound
websocket connection and relay messages) using reactphp and found it to be
nearly impossible due to language/framework constructs.

It was easy enough to make the outbound connections but there was no obvious
way to actually pass messages between the two connections.

Async style really just does not seem to work well with php at all.

~~~
francislavoie
I recommend looking at ZeroMQ for this

~~~
jameshilliard
Not sure how that would help much, I needed something that could talk with
redis and websockets and pass messages between the two. I was trying to use
php since that's what the main portion of the application was implemented in
so that I could share code, I ended up just using python in the end though.

------
firefoxd
I remember when node was new and everyone was trying those real-time chat
tutorials. After following the cliché tutorial i realized in order to share
the session between node and the rest of the php app I had to basically hack
it.

I ended up having to read the source code of ReactPHP and add the
functionality to my framework. Sure it is not one line of code like with node,
but it's not rocket science either. I would definitely recommend trying
ReactPHP to see the benefits.

------
dillon

        ... our CPU has to wait and does nothing, instead of doing some useful job.
    

Please correct me where I'm wrong, but IIRC your CPU is never waiting if there
is more work to be done. Yes, there is the overhead of context switching if
you're using mod_php. Otherwise I think most operating systems are smart
enough to make use of resources.

EDIT: Maybe an OS expert can clear up how this works?

~~~
q3k
Correct. If a process is waiting on a recv()/send() (or any other non-
asynchronous IO syscall on Linux), the userspace process will go into
(un)interruptible sleep and another process can be scheduled in it's place.
When data is ready to process (or a signal needs to be delivered) the original
process will be scheduled again and the syscall will return. It would be
absurd for the CPU to busy wait on data.

And if the language you're choosing is a slow interpreted language like PHP
then I'm fairly sure the context switch overhead is negligible.

------
vatotemking
Slightly off but, what I loved most about Node's async/await is that its
backwards compatible with promises.

Most of the third-party packages were built during the promises and callback
era, and I'm so happy I can still use them. Imagine if its a BC break ala
python 3, that would certainly fragment the community and would hurt the
adoption of version 7.x.x and above.

------
obvio
Event-driven asynchronous & concurrent & coroutine networking engine with high
performance for PHP. [http://www.swoole.com/](http://www.swoole.com/)
[https://github.com/swoole/swoole-src](https://github.com/swoole/swoole-src)

------
jv22222
What are some of the best resources to use when getting started coding async
PHP? Any tutorials?

~~~
CharlesW
Here's a list you might find useful: [https://github.com/elazar/asynchronous-
php](https://github.com/elazar/asynchronous-php)

------
tylerjwilk00
Brace yourself for virtue signaling about how bad PHP is because <insert wart
from 10 year old version>. On a less cynical note, working in both Node and
PHP, async is often more cumbersome than it's worth (for me) and a queue
suffices.

------
el_cid
just use NodeJS or Go

~~~
slifin
JavaScript is a worse language than PHP in some ways, for example no native
type hinting, no native filter map reduce on hash tables, no explicit variable
import into scope

I'm not saying PHP is a better asynchronous language than NodeJS but I'd
definitely be wary of JavaScript unless you're interested in compiling

If you're interested in compiling then there are some very good languages in
that space that are not JavaScript, Go, #F, etc

~~~
tiuPapa
Use typescript or flow if you want types.

~~~
JupiterMoon
Now we are compiling (sorry transpiling). If we are going to do that why not
use e.g. Go?

~~~
jrs95
Technically transpiling is just a more specific kind of compiling, so you’re
not wrong in saying compiling.

------
foxhill
i'm sure the spec for async in php is well designed and implemented.

(is "/s" still a thing?)

------
EngineerBetter
PHP was originally called Personal Home Page Tools. Perhaps people should
consider that before building large and complex systems using it.

~~~
hluska
You know, I understand a certain amount of PHP bashing. It's far from the most
sane language that I have ever used and parts of the syntax are flat out
painful.

That said though, the version of PHP you are talking about was written 23
years ago. The language has changed a tremendous amount over 23 years. The
state of the tool 23 years ago would be a very poor reason to choose or avoid
it today.

Hell, Java is roughly the same age as PHP. Nobody in their right mind would
dream of using that first version of Java today. It isn't that the tool itself
is bad. Rather, the tool has improved dramatically over the last two decades.

~~~
ams6110
> It's far from the most sane language that I have ever used and parts of the
> syntax are flat out painful.

Also applies to JavaScript, and to be fair, many other scripting languages.
None of them were perfect in v.1 and to add missing features it was often
necessary to bend them in ways that are inconsistent with the rest of the
language.

