I have read some beginner books and so many articles about elixir, and everyone was appreciating the concurrency & synchronization in elixir. But in my thinking everything has some pros and cons, everyone talked about the pros, but no one really mentioned the cons of concurrency & synchronization in elixir.
The only con ai can think of is that concurrency is a lie. I mean, on many machines you will get concurrency, but in its nature, Erlang is parallel, not concurrent.
Other than that there isn’t much issues, maybe except the fact that many people think that throwing more processes at things will make things faster, which is obviously false.
In order to answer that question, I think we need to recap how Elixir/Erlang handles concurrency and synchronization: Isolated processes that communicate via messages, and general immutability of data.
If we leave ETS out of the equation for now, that means that nothing is shared between the processes.
When one uses multi-thread programming as a concurrency paradigm, the rules are different: Memory is shared, and one must ensure that this does not lead to trouble using semaphores or lock-free algorithms.
The disadvantage of Erlang’s approach is that someone has made a choice for you. You cannot easily share data between processes and you cannot easily implement your own lock-free algorithms.
So there are situations where it is not possible to achieve the same performance in Erlang as you can using multiple threads.
That being said. I think that in most cases the process-based model with messages being the way to exchange data between them, is vastly superior to threads.
The model has also been copied to many different languages and environments. Probably because it is much easier to work with, and because the drawbacks are few.
Obviously the con is when you absolutely positively need synchronization / barriers / semaphores / mutexes like in a normal DB engine.
Another con could be that the preemptive scheduling nature of the BEAM loses some CPU cycles to achieve the godlike responsiveness of the runtime. People working with lower-level languages, especially Rust lately, are efficiency fanatics and disagree with that tradeoff. (Although some that I have worked with admitted that the Erlang’s idea of processes with isolated mailboxes would kill 90% of the bugs they encountered in their code.)
I’m a big fan of cons included when there’s a bunch of pros. However, I was racking my brain a bit to think of practical cons with the approach in Elixir.
For me, efficiency is not necessarily a practical con because I wouldn’t say I was ever hindered by the parallelism of Elixir. But I can appreciate the approach it takes having an overhead and people considering that a con.
To me, maybe the biggest con is that parallel and synchronous code are something that can trip people up. It’s not this magical system that prevents coding or understanding errors. A person may think some code is parallel but then it converges into a synchronous choke point because they missed something.
Speed. Erlang (and elixir) are opinionated about how to achieve concurrency. Those opinions cost you processor speed. It’s not much, bit it’s real. Your elixir will never be as fast as go or java (but it will be faster than python or ruby).
For most people if they think they will need cpu speed are fooling themselves. It is no longer the 90s (or earlier) The bottleneck is usually somewhere else.
That’s frankly a selling point to me. I wouldn’t put Elixir in a competition versus Go or Java or Rust. However, Elixir does seem to be one of the fastest dynamic languages out there (and I mean top 10, if not 5 even).
So in its segment Elixir is quite impressive in terms of speed.
Could you clarify this? The terms ‘parallel’ and ‘concurrent’ are often confused and there is also some middle ground for which people disagree over whether it falls under one or the other.
To my knowledge, paralellism = doing the same task many times side-by-side (on slightly different data) whereas concurrency = doing different tasks at the same time.
That’s not the difference.
Concurrency: Interweaving the completion of multiple tasks, instead of completing one after the other. (Works on a single core machine)
Parallelism: Doing multiple tasks at the same time (needs multi core)
These two definitions I know under the terms multitasking (interweaving multiple tasks on a single core) and multithreading (doing multiple tasks at the same time) respectively.
EDIT: I stand corrected. The definition you mention seems indeed very common and probably is ubiquitous. I should have a talk with my parallel computing professor from back in the day, he did not explain it very well.
It is important to remember, that you need concurrency to make things parallel, but you do not need parallelisation for concurrency.
Wait I’m confused. You said that concurrency is a lie and that’s it’s parallel but not concurrent. But it is parallel (meaning it’s also concurrent). I’m missing something but not sure what.
Concurrency can be achieved on a single-core machine. People did it for decades, long before multicore CPUs existed. Hell, I did it on my Apple IIc when I was a teen (switching between several programs with strategically placed interrupt CPU commands).
Parallelism means to literally and physically have separate programs working in parallel (not emulated via insanely fast switching like a single-core CPU concurrency does).
That’s how I understood it at least.
Concurrency = giving time slices to different processes from same CPU core.
Parallel = processes running on different CPU cores.
If I’ve understand Erlang’s VM BEAM correctly it decides how processes are run they could run concurrently or parallel. But usually they are running processes concurrently with other processes because you quite likely have so many of them that they exceed double amount of CPU cores.
Yeah, I messed the two terms in my first post. It only shows that it is confusing
Whenever one tries to compare programming languages like this I always have to think about this Rober Virding quote:
Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang. Link
It definitely is. @dimitarvp did a great job laying it out for us up above
Well said. This is a central point to understand I think. I.e. if you are unhappy with the speed of Erlang and choose C or Rust then you’ll not get the preemptive concurrency. This is fine unless you start getting unhappy with C/Rust/[…] and try to bring preemptive concurrency into them. If you try so you will end up with a buggy slow own implementation of Erlang. Yet put into other words that means that if you are looking for the features that Erlang gives you, you cannot find a faster and more reliable implementation.