For what it means for concurrency, it's not intended to be a high performant number crunching system, but rather one built to to make concurrency safe (which ends up being extremely performant for I/O bound workloads, and extremely predictable for CPU bound ones) - M:N threading model, immutable data, shared almost nothing, achieved via the actor model.
"Concurrent applications" as in the C10M problem (http://c10m.robertgraham.com/p/manifesto.html): servers serving a lot of clients at once; usually with the added assumption of a diverse request workload (i.e. some requests are IO-bound, some are CPU-bound, some are long, some are short, etc.)
• WhatsApp used Erlang (on FreeBSD) to scale 50 engineers and ~1000 boxes to handling billions of chat-message transactions per second. (https://www.infoq.com/presentations/whatsapp-scalability/)
• A lot of modern financial infrastructure (banks, exchanges, etc.) is built on Erlang. If there's a financial system that can get away with not being hard-real-time, chances are someone's considered writing it in Erlang.
• Many massively-multiplayer games have Erlang in their backends or their networking middleware.
• And, of course, the original point of Erlang was to route (millions of concurrent) calls in Ericsson backbone telecom routers. It can be deduced from Ericsson's continued work on Erlang's "megaco" H.248 application, that they're using Erlang in their LTE IPMS gateway appliances, to route cell-subscribers' VoLTE audio- and video-call frames.
> Is it like nodejs but more performant?
Node.js is decidedly bad at this type of concurrency (although its libuv is used successfully in software like Nginx—it is rather Javascript's thread-isolation semantics that bottlenecks Node.js code, not V8 as a runtime.) A better comparison is with Golang. If you put Node and Golang on a spectrum of "ability to handle highly-concurrent heterogenous workloads", then Erlang is a point much further along that spectrum than either of them.
(Golang gets pretty far if the workload is homogenous, though. And you can get even further still on that spectrum with custom C or JVM code; but in the process, you'll likely sacrifice either 99th-percentile latency, or lock yourself into coding in terms of state machines. Erlang sits an an optimum where you can just write blocking code in actors and it does the right thing, predictably, even when you have millions of actors.)
This is what I missed the most about Erlang when trying to use Akka's actors - the simplicity of writing a function that blocked until it received a message made for far more straight forward code.
Ok, WhatsApp does scale exceptionally well with very little resources, but those number aren't really accurate.
It is not billion messages / second, that would imply majority of the WhatsApp user were awake and send a message in the same second. But right now it may be more than a million per second. During its FreeBSD era ( They switched to Linux when Facebook bought them ) it was doing ~400K messages / sec during peak. And it is not 1000, during it FreeBSD era is was handling it with less than 150 server for Chat. And that was with a very non powerful 10-Core Ivy Bridge Servers. I often wonder if they could handle the same in 20 Servers when we have 128 Core Per Server today.
Or something else?
Imagine you took all the AWS Lambda functions of all the different Lambda users, compiled them together into one binary, and then ran that single binary on one huge vertically-scaled server, allowing all the Lambda tenants to hit that server to run requests against their own workloads in the address-space of that single binary. That's a clear "heterogenous workload": one where you've spawned a bunch of green-threads within your process, and those green-threads are all trying to do different things. It's a million little job-shops under one roof (with, importantly, only one "door" in and out, that everyone has to coordinate to share); rather than one big factory where a million workers each have a defined job and there's a big loading bay that is declared from the top to be exclusively owned-and-operated by one department.
Erlang handles the "million job-shops under one roof" use-case pretty well. Golang kinda-sorta handles it, but kinda falls over, too, because the Golang runtime (and the whole concept of reifying typed channels as objects) isn't tuned for the case where each task has spawned an ephemeral digraph of communication paths between ephemeral actors. Channels have a Golang-runtime-system overhead just for existing, a bit like processes or sockets do for the OS. So, like processes or sockets, you're not supposed to just create a channel for each little thing until you've got a million laying about; you're supposed to reuse or share them (and the goroutines they address) between multiple workloads.
Idiomatic Golang code is written in a more dataflow-y pipeline-y SIMD-y way (the "factory with a million workers" above), where you've got static "actors" sending massive amounts of work between them, perhaps tagged with the request they're "about." When this is the 'data architecture' of your code, the Golang runtime can actually beat BEAM (using an equivalent architecyural abstraction, e.g. https://hexdocs.pm/flow/Flow.html) in both throughput and latency, since it's exactly what the Golang runtime has been tuned for.
The downside of the dataflow approach is that, compared to actors-as-little-Turing-machines, dataflow is a very hard data-architecture to reason about! (And also tends to mean that a logic error in any of your static dataflow worker-actors, causes a lot of "collateral damage" when it comes down, to the point that it often may as well bring down the whole system with it. A stall in an assembly line stops the whole factory; but a stall in a job-shop doesn't stop the whole economy!)
It's not a language oriented at maximum throughput of parallel operations.
It is a language that is oriented at providing very low latency (soft real-time) handling of lots of events.
When you write in Erlang, you decompose your program into lots (think upwards of millions) of small user-space processes, that communicate using asynchronous messages.
One side-effect of this architecture is that your application will scale in performance as you add more cores without having to change the code.
It's a great language for server applications, like NodeJS.
It also has a number of features that make it great for embedded and IoT type applications (which is why it was created in the first place).
But you might want to check out someone who knows better, like Rob Pike: https://www.youtube.com/watch?v=cN_DpYBzKso
Yes, Erlang makes concurrent programs easier to write.
Again it is better to listen to someone who knows more, like the creator of Erlang Joe Armstrong: https://www.youtube.com/watch?v=bo5WL5IQAd0 Any talk by him is great.
Erlang, in how i see it, makes it easier to write concurrent programs because:
1. Parts of a program communicate with other parts by passing messages
2. Every variable is static, as in if you declare that A is 12 you can not change it to be 13
Joe Armstrong had a way of explaining these things so that even i could understand, so i do recommend watching every talk you can find of him. I also recommend the interview he did of Alan Kay https://www.youtube.com/watch?v=fhOHn9TClXY .
But if you want to really get into concurrency i recommend a paper called "Communicating Sequential Processes" by C. A. R. Hoare. See http://www.usingcsp.com/
It's a "formal language" for dealing with concurrency. Go, and some other languages, implement a "CSP style" way of doing concurrency.
Erlang doesn't do SIMD, nor GPU. However, it does world scale low latency systems.
Of course, it's still up to the programmer to do everything correctly and Erlang is just a tool.
I don't quite like *JS, so i won't say anything about that.
Since one computer can fail, your programming language should be designed to be run on multiple computers. Erlang's the only language I know about that puts this philosophy first and foremost.
This proceeded Erlang by 24 years or so. I know it's not the language, and a combination of hardware and software, but they did change the instruction set of the HP 3000 to have paged virtual memory and "share-nothing" messaging system.
Also see the Pony language: https://www.ponylang.io/
It goes way back, 1998 was when they open sourced it, the language was in development and use inside Ericsson since 1986.
I have used Erlang's venerability in other Erlang postings, but for some reason I guess the open sourcing date stuck in my head.
Node is mostly single-threaded still, right? The Erlang VM, Beam, runs truly concurrently. Also, a few large pieces of CPU work cannot block the scheduler indefinitely. I'm not aware of a runtime that works quite like it. Suits me well. I use it throigh Elixir.
It is not the fastest in any given metric from what I know but I think it delivers enormously well in real life scenarios.
Does it make concurrent applications easier to write? Does it make it easier to use the SIMD instruction set, how hard is it to get a function written in erlang to run on a gpu?
Is it like nodejs but more performant? I appreciate anyone who has answers here, I try to position all the relatively interesting things I don't have much time to dive in to in a mental model with opportunities for future promotion.