The official Erlang/OTP team blog, with posts on BEAM internals, the compiler and JIT, and highlights of OTP releases.
HN links it for explanations of the BEAM and compiler work, including OTP 22 improvements to binary pattern optimization.
I am not familiar with the issues affecting the referenced languages to make an efficient comparison, sorry. But I can add some context if you are interested in looking further.
First of all, let's talk about the memory model. The Erlang VM manages memory per process (where a process is a lightweight thread of execution inside the VM that runs concurrently and you can literally have millions of them). So for example, when you have a web request, you spawn a separate process for this web request and once the process terminates, all the memory allocated to it is reclaimed by the VM. This means you can serve a web request without triggering a garbage collector even once. And if you need to garbage collect, it is local per process, so no system wide pauses.
However, what happens if you want to share a large blob of memory between processes? If you copied it between each process it would be expensive, so in this case the VM employs reference counting.
One curious point is that the Erlang VM did not give allocated memory back to the OS until Erlang/OTP 22 (roughly two years ago). This was not much of a problem in the Erlang VM because you typically run only one instance of the VM per node, regardless if you have 4 or 32 cores. Given the issues you mentioned in Python/Ruby/Node, could it partially be because you would rather start 4 or 32 instances per node, so if one of them accumulates too much memory and doesn't give back, it starves the other ones? Or perhaps you would have…
Highlights:
> In OTP 22 we have completely re-implemented the lower levels of the Erlang compiler.
Meaning some performance improvements for bit syntax which in Erlang is used [EDIT: in some of the newer, external code; there are still many places where charlists are used] for strings. Some string BIFs got faster. This should translate directly to Elixir and its string handling functions performance.
> OTP 22 comes with a new experimental socket API. The idea behind this API is to have a stable intermediary API that users can use to create features that are not part of the higher-level gen APIs.
Other than the ease of extending the API there are some performance improvements, too.
> PR1952 contributed by Kjell Winblad from Uppsala University makes it possible to do updated in parallel on ets tables of the type ordered_set. This has greatly increased the scalability of such ets tables that are the base for many applications, for instance, pg2 and the default ssl session cache.
More concurrency, better performance.
> In OTP 21.3 the culmination of many optimizations in the ssl application was released. For certain use-cases, the overhead of a using TSL has been significantly reduced. [...] The bytes per second that the Erlang distribution over TSL is able to send has been increased from 17K to about 80K, so more than 4 times as much data as before.
Everything relying on ssl got faster.
> On OTP 22 the logging facility for ssl has been greatly improved and there is…
So, kind of a non sequitur, but I occasionally think about Qt's QList<T>. When introduced, it was odd for reserving space at the beginning as well as the end, so you had constant-time inserts/removals at the beginning. That and storing pointers for any T larger than a pointer also reduced the constant factor on insertion/deletions from the middle. Since it was always stored as a list of pointer-sized items, some code could be shared between implementations for different types, so your program's binary could be a bit smaller. I think they said at the initial release that they benchmarked a bunch of options in some real code and this won.
That was waaay at odds with the mindset of the STL, which seemed to me and I think a lot of folks like the state-of-the-art of containers at the time: with the STL if you prepend/insert much you need to use a deque/linked list, you decide pointer vs. value each time you declare a type, and if you want to know about the constant factor on an insert in the middle of the list you probably already lost.
(Qt has/had some other fun pragmatic things, like copy-on-write types in a lot of places. I didn't really do nearly enough with it to discover the pitfalls, but was fun to read.)
So I think about that, about how there are likely some trees out there that could just as well be sorted arrays, about adaptive structures that change their behavior based on dynamically observing how they're used (one recently discussed here:…
I haven't looked at QEMU's TCG much, but I doubt it would be a good choice for bytecode formats even if you could bash it into doing something useful as part of a backend. I'd expect it to be optimized for hardware-CPU-alike machine instructions, whereas BEAM is Bogdan's Erlang Abstract Machine. See https://blog.erlang.org/a-brief-BEAM-primer/ which points to https://github.com/erlang/otp/blob/master/lib/compiler/src/genop.tab. If you look into how some of those are implemented, just as one example, the integer arithmetic operations handle automatic promotion to bignums—not something you'd find on a conventional CPU, but not uncommon in HLL bytecode. So you'd still have most of the implementation to do—and if you punt and hardwire all of those to runtime library calls, you're almost back in threaded-code land anyway; you really want to take specialization opportunities etc. into account…
I also don't know of any other HLL JITs that use TCG, which seems like weak evidence that it wouldn't be a win.
This is the gist of it:
"The primary motivator for Lumen's development was the ability to compile Elixir applications that could target WebAssembly, enabling use of Elixir as a language for frontend development."
I had to dig to lean what BEAM is :)
"Bogumil Hausman next machine was called BEAM (Bogdan’s Erlang Abstract Machine). It was a hybrid machine that could execute both native code and threaded code with an interpreter. That allowed customers to compile their time-critial modules to native code and all other modules to threaded BEAM code. The threaded BEAM in itself was faster than JAM code."
http://blog.erlang.org/beam-compiler-history/
I now feel a little less bad that I couldn't figure out the acronym :)
+1000
I couldn't agree more. I have a lot of hope for BEAMJIT (or anything that will make Erlang faster per clock cycle).
http://blog.erlang.org/My-OTP-21-Highlights/
After reading the link above, I get the sad feeling that a faster Erlang isn't anytime soon :(
With that being sad, Elixir has brought a whole new wave of people to the OTP community. Which excites me tremendously. I just hope a faster Erlang will arrive soon enough so that people needing to leave Ruby due to slowness have a good alternative with Erlang.