BEAM is never going to win for straight line speed. This is going to be an improvement for a language optimized for resilience, concurrency and consistency.
Running millions of concurrent processes, with their own heap, with consistent response times that individually tolerate failure without negatively affecting the entire system is just a different animal with a different set of trade offs.
Not for you. But I know quite a bit about the guts of the BEAM VM and I think this is a very interesting development and if the jump is large enough it may well obviate the need for a whole slew of situations where you now have to fall back to externally loaded functions in different languages, and that would make a bunch of stuff far more elegant. Yes, those externally loaded functions will (always) have a speed advantage, but if the advantage drops below the level of the cost of adding an external module then that would be pretty good news.
If you are allowed to write e.g., a Java program and run it on the JVM, the speedup will typically be on the orders of magnitude in favor of the JVM. Static type systems and extensive optimization matter.
However, chances are you have an Erlang program, and it's quite large. In this case, the speedup compared to the older bytecode interpreter is good for many programs. It is performance you get "for free" by upgrading.
The underlying reason for picking something like Erlang is robustness. Java isn't really built for this kind of programming, and the JVM doesn't directly facilitate it either.
I don't think the two JITs really do the same work, so it's hard to benchmark them against each other.
Erlang JIT takes BEAM bytecode and turns it into native code once at load time in order to avoid the overhead of the threaded code interpreter; if Erlang JIT is enabled, the interpreter is not used at all. Java's HotSpot JIT takes JVM bytecode and turns it into native code at runtime in order to improve performance of code that is run frequently (thus the name), guided by runtime information; lightly used code will be interpreted, heavily used code will hopefully be JITed to native. When HotSpot JITs, it may apply assumptions based on runtime use to produce faster code and if the assumptions don't hold for a call, the interpreter can be used instead (and if that happens often enough, the native code can be discarded and perhaps rebuilt), so the interpreter needs to be present always.
Erlang JIT has been focused more on always applying and speed of application (because it delays code loading), whereas HotSpot focuses more on getting performance gains when it applies, and speed of application is less important because it happens asynchronously. So if you benchmarked speed of applying the JIT, Erlang would probably win, and if you benchmarked optimization of the code, HotSpot would probably win, but either way you're comparing apples and oranges.
The JVM is nearly as fast as hand optimised C, this is not intended to be that fast, rather a simple bedrock to build further optimisations into. Immutable everything also will limit performance as will the focus on latency at the cost of everything else. Not sure of actual performance compared to JVM though, I wonder if it’s as far away as I expect…
Erlang JIT is still very simple, unlike highly optimized super complex V8 jit. It's faster than non-jit erlang, sometimes twice as fast, but nowhere near nodejs-fast. Erlang team don't have resources to make and maintain such complex beast. (everything said here is about raw performance)
Some of the things I like better about Elixir and Erlang vs. Go and Java are:
- In Elixir/Erlang, all processes are stored in private memory and can only be accessed via defined message interfaces. In both Go and Java, processes are stored in public memory.
- Elixir/Erlang processes are a lot smaller, memory-wise, than Go/Java processes.
- We moved all of our development at my current company from Java to Elixir because Elixir, being functional, makes writing multi-threaded applications a lot faster/easier. Elixir is also cheaper to deploy. At least that has been our experience.
- I like the syntax of both Elixir and Erlang better than Go, Java, or JS.
- I don't have as much experience with Node/Express, but in my limited testing with Node/Express vs. Elixir/Phoenix, the latter is several times faster and much more scalable. It also makes better use of hardware (which I believe is discussed in the link above).
I hope at least some of this helps answer your question.
Running millions of concurrent processes, with their own heap, with consistent response times that individually tolerate failure without negatively affecting the entire system is just a different animal with a different set of trade offs.
You’re trading some speed for those benefits.