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
What's your point? All interpreted languages have to be compiled anyway, you have to create an AST, convert it to bytecode, and then interpret it or JIT it.
You joke but this is exactly what should be done. Python also has an async story that leaves a bit to be desired. Async/await etc is getting more and more use, but with async coroutine mocks and everything it seems easier to start over sometimes.
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.
> 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.
So you start with PHP, and you keep adding hacks on top of hacks, until you realise it's hopeless. But you're too invested, so you create a new language that is kind of compatible, and a JIT for good measure. Of course, I hope you got really successful, because you'll need serious engineering talent and money.
No language/tech stack is going to ensure success, or have no challenges. But learning from the past is not a weakness.
The lesson I see is that any language, even PHP, will give you success if you "build something people want".
I read lots of startup "shutdown" stories - and I've not read one that mentioned the choice of "PHP" (or any language) as the reason for shutting down.
So if your comfortable with PHP - punch out what you need to get started...
Businesses usually don't fail because of picking a wrong programming language. If the tool that's best for the job is not the same as the tool you can make what you want the fastest, I'd say go with the tool that gets you where you want the fastest, even if it isn't the best. If you're successful you'll have money to fix that later on. If you're not successful then it doesn't matter which tool you picked anyway. If Zuckerberg would've learned another language first, there might not have been a Facebook.
Or you use sane development practices, well supported libraries and frameworks, and the latest version of PHP and run very successfully, because it's more than fast enough, shared nothing is a viable paradigm and being able to quickly see the effect of code changes without compiling and redeploying into a container is something you miss when working in the Java world.
Is it suitable for EVERY application? No. But then again, nothing is a one-size-fits-all solution for all problems.
> 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.
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.
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.
Or, even better, you could just use a language that works well with concurrent programming without having to shoehorn in abstractions that break 2% of the time. Go, Haskell, Erlang, take your pick; any of them will work correctly out of the box, even if some library does blocking FFI calls.
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.
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.
The queue is given the command. The command has the functions I want to run, including the context and what I want done with the result. It can be a closure right up to a full class.
Using a framework like Laravel I can even "chain" queued commands - so CommandA will queued, then call CommandB when it is done etc.
I've never run into a situation that wasnt easily solved by this.
OK so what environment is the function being executed in? That environment is outside of PHP. Now when it comes time to do the callback, is the PHP thread still running, or not?
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.
+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.
Note however that these queue systems are not really PHP. You need supervisor (Python) and beanstalk (C) for this to work. Laravel just abstracts it away. And its good if everything is working until its not (hard to debug).
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.
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.
I agree with this - everything should be sync first and async when needed with a keyword (similar to how Go has goroutines and channels, coincidentally this is how UNIX executables and streams traditionally worked). Javascript gets it just exactly backwards. Going from imperative to functional programming is like leveling up, and it's very hard to go back down to mutable variables, side effects and nondeterministic flow control. So I understand why Node devs prefer async how it stands now, but it's hard to unsee Go/Elixer/Erlang once it clicks.
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.
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.
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.
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 :)
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.
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.
... 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?
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.
On the topic of asynchronous PHP, swoole (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.
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.
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.
61 comments
[ 3.6 ms ] story [ 121 ms ] thread(is "/s" still a thing?)
https://amphp.org/ https://reactphp.org/
Was basically the article. r/savedyouaclick
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
True, but you can use TypeScript, which I expect is more advanced than PHP's typing.
>no native filter map reduce on hash table
What do you mean by that? There is Object.keys/Object.values/Object.entries.
>no explicit variable import into scope
What do you mean by this? You can import a variable from a module.
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.
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.
No language/tech stack is going to ensure success, or have no challenges. But learning from the past is not a weakness.
What's the lesson you are learning from?
The lesson I see is that any language, even PHP, will give you success if you "build something people want".
I read lots of startup "shutdown" stories - and I've not read one that mentioned the choice of "PHP" (or any language) as the reason for shutting down.
So if your comfortable with PHP - punch out what you need to get started...
Is it suitable for EVERY application? No. But then again, nothing is a one-size-fits-all solution for all problems.
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.
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
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.
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.
Using a framework like Laravel I can even "chain" queued commands - so CommandA will queued, then call CommandB when it is done etc.
I've never run into a situation that wasnt easily solved by this.
The majority of the examples out there are indeed contrived and better suited to a queue system as you've described.
Note however that these queue systems are not really PHP. You need supervisor (Python) and beanstalk (C) for this to work. Laravel just abstracts it away. And its good if everything is working until its not (hard to debug).
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.
I am confused by this. JavaScript is synchronous and blocking by default due to its single-threaded nature as far as I know?
Sure, async will yield different behaviors for functions than without that decoration but that's a very new language feature.
`let res = await someAsyncOperation();`
and whenever you want an async operation (non-blocking), thats when you do something like:
async { let res = someAsyncOperation() }
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.
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.
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.
I just came here to say that ... neither was Javascript :)
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.
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.
EDIT: Maybe an OS expert can clear up how this works?
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.
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.