Functional PHP (2015)
fluffyandflakey.blog
fluffyandflakey.blog
Different trade offs for sure, but given IO is often the bottleneck, having it force you to think about running code asynchronously can often result in code that runs more in parallel than equivalent first blush php code.
For instance, if you were writing in a function style a program that fetched entries from a web service, for each of those results, run a summarization pass using another service, and then insert summarization result in a database, a style like shown in this article might serialize the summarization / insert operations, one after the other, where you’d instead want each result to be processed in parallel.
Lots of libraries in node that make that easy and the code straightforward to reason about.
eg this
function sad(input) {
return new Promise((resolve, reject) =>
foo(input).then((data) => {
bar(data).then((data2) => {
baz(data2).then(resolve, reject)
})
})
);
}
could quite as easily have been written like this: function happy(input) {
return foo(input)
.then((data) => bar(data))
.then((data2) => baz(data2))
}
But no one seemed to be aware that you can return a promise in the `.then()` callback and have it chain neatly...That's not because it's bad - it's a useful tool if you're connecting event or callback-based systems to the world of promises and async/await. But a lot of people who are just getting started with promises seem to take a while to get used to chaining, and often resort to using the `new Promise` constructor to get promises to appear in the places they expect. So giving them a blanket rule ("never use `new Promise`") forces them to figure out a different approach.
It's become a lot easier since the introduction of async/await, where chaining isn't so important, but there are still always times when you need to understand that underneath the syntax sugar, there's still promises happening, and so I'm still finding the rule useful.
I haven't used node in years, so i wonder: What is used instead?
If you set up a Node script where e.g. Express talks directly to the clients, then yes, the script crashing or hanging means the server becomes unavailable or unresponsive. However, you can also set up a layer in front of Node. See cgi-node for replicating the CGI workflow you might be used to.
There are some advantages to the standard Node model though: the program can manage its own resources, such as keeping a database connection open; it can run asynchronous maintenance tasks; it can see and report the current server load; it can easily combine HTTP(S) communication and Web socket streams; etc.
Not exactly... the standard, typical LAMP stack makes use of mod_php, so the PHP engine is in-process with one of the Apache process.
The fact that Apache has multiprocess/hybrid workers is actually why the server stays up and can serve more requests.
Some contemporary LAMP stacks use FPM, I guess; most of those in shared hosting ISPs for example because of the possibility of running the script as a user process.
The main tradeoff is you’re now reloading the entire server for every request in PHP. If you have a massive server or framework, that might not be the fastest thing in the world.
Some frameworks like symfony considered removing preload support but they were still seeing benchmarks of 10% better performance with it so it was kept.
The biggest pain point with preload IMO is it's global, not per pool, and php-fpm needs to be restarted to update the preload script.
The most common PHP setups are simply running multiple processes behind a httpd daemon, so this problem is less frequently encountered. But it's still lurking at a certain concurrency level.
Btw while this code doesn't win a prize, I agree with the author that functional style is worth it in many cases, even for a language as wordy and cumbersome as PHP. I still love PHP - its deployment story is still unparalleled and its standard library came batteries included since forever.
A big issue though (at least for some apps), is there is no attempt to make that code parallelized for the io parts. So if you aren’t careful, you can end up with n+1 style IO calls, making things very slow.
Writing pure FP code (pushing all the side effects to the "edges of the program" in C is possible! But it's going to take a lot of discipline from the programmers: there is no safety-net and lots of dreadful boilerplate.
Impracticle, but possible.
> Instead of fearing the overhead in PHP for function calls,
Already in 2015 in almost all applications this is a premature optimization which is rightly known as the root of all evil. Please. Your app will talk to the network, likely run a database query which is like thousands or millions of times slower than a function call. Further, even if there is a measurable difference the cost of hardware which makes that difference go away is very likely to be smaller and much smaller at that than the cost of the engineering hours wasted during maintenance when wrestling with code which was written with a "function calls are expensive" mindset.
This doesn't mean you don't need to worry about performance and scalability but even that is going to be much easier if you have a well structured code.
Your point still stands that fundamentally changing the design of code should limited to the hottest parts.
Probably the biggest risk to this style map/reduce code is that you end up having IO deeply nested running synchronously versus grouping operations that can be run in parallel.