Functional Programming in a Parallel World

Lambdaman

A Bit of History

Several decades ago, memory was a very precious and limited resource, so it made sense back then for our software to take hold of some piece of memory and mutate it as much as possible. Computers weren’t powerful enough in terms of memory and processing to handle the abstractions required by some functional programming languages, such as immutability, pure functions and referential transparency. That’s why many functional programming languages ended up being relatively slow for most non trivial tasks and were rarely used outside the academic world.

For the reasons stated above and many other historical events, the Imperative Programming paradigm began its clear domination in the software ecosystem, specially after the born of the C programming language and many other languages that derived from it in the decades thereafter, such as C++, Java and PHP. On the other hand, most functional languages such as Lisp and ML had a very important place in the Academy due to their close relationship with Mathematics, Linear Algebra and the Lambda Calculus (λ).

State of the Art

Today’s reality is that computer processors are not getting any faster due to a physical limitation in the size of transistors, causing a radical change in the architecture of CPUs, moving from single to multi core units. In today’s world we see processors with 4, 16, 32 and even more cores! This means that modern software needs to use efficiently as many cores as possible in order to maximize the system resources usage.

It’s a known fact that mutating the state slow down considerably the execution of a program when many cores are involved. If you have four or more cores trying to access and manipulate the same piece of memory, there is a high risk of data corruption unless you implement complex synchronization routines.

Shared mutable state is the root of all EVIL. Parallel processing combined with shared mutable state produce unpredictable and non deterministic programs.
nondeterminism = parallel processing + mutable state
Martin Odersky

When it comes to programming a multicore processor, the benefits of having Immutability are huge! If you use a conventional imperative language such as Java or Ruby to develop multithreaded programs, you probably will have to deal with problems related to Shared Memory, so in order not to corrupt the memory, this must be blocked while it is accessed by another routine, which not only makes the overall program more difficult to parallelize but also more difficult to reason about.

Functional Languages to the Rescue

The use of pure functions means the absence of side effects, and the absence of side effects means the possibility of parallelizing a program in a relatively simple way. Since there is no Mutable State in pure functional languages, there’s no shared memory and so it’s not necessary to write complex synchronization routines any more. These and many more attributes make functional languages a no-brainer when it comes to developing parallel programs, since you are maximizing the system resources usage which has a huge impact on infrastructure costs.

There are several companies whose services demand an extremely high level of concurrency and availability, that is the case of WhatsApp, messaging app with over one billion active users, whose backend is mostly developed in Erlang (functional and concurrency oriented programming language) on top of the Erlang Virtual Machine (BEAM). In 2012, more than 4 years ago, WhatsApp reported that managed to run more than two millions of concurrent connections per server, using less than 40% of the server resources with a relatively small engineers team (see WhatsApp case). Today WhatsApp is a company that process more 42 billion messages, 1.6 billions of photos and 250 millions of videos per day! All of this with less than 60 engineers.

Conclusion

I think that the sequential programming era is about to finish. Thanks to globalization and universalization of Internet, modern software demands to be highly scalable, distributed, fault tolerant and primarily concurrent, and that’s exactly when functional programming languages like Elixir, Erlang, Haskell, OCaml and Clojure come to the rescue.


I’ve just began the interview process at Toptal.com (to become a part of the Elixir engineers community), and I’d really like to get in and become one of the freelancers who work there. If you’re a software engineer looking for work, I recommend you to do the same.