markdev
Elixir vs. Erlang benchmarks - is one faster than the other?
Is there any significant difference in the runtime speed of programs written in erlang vs. elixir? What (if any) advantages are there to writing one’s source code in raw erlang instead of elixir?
Most Liked
josevalim
Yes! Elixir is slightly slower because we dispatch to Enum.reduce and Erlang doesn’t perform a remote call.
We inline most common types with the list type coming first. So for the builtin types, that should be no difference in performance.
@compile {:inline, ...} only works within the same module so it is not a general mechanism for wrapping Erlang functions. The Elixir compiler, however, does inline most of its calls to :erlang.
So there are tiny differences in some very specific cases, but they are quite unlikely to matter in general.
benwilson512
There are no differences, both compile to the same byte code. Erlang is not more “raw” or low level than Elixir.
michalmuskala
Maps have actually two representations depending on the size. Small maps (less than 32 keys) are represented as two sorted arrays - one for keys and one for values. Accessing a key in such a map involves a linear search (and a linear search is much faster than a binary search since the size is so small). Depending on how you look at it, you might say that’s O(n) since it depends on the map size, or O(1) since the worst case is O(32), which is O(1) - the big O notation is not very helpful when talking about small data structures, especially with cache locality and branch prediction effects, you can get significantly different results from what you’d expect by a simple complexity analysis.
Large maps are represented as HAMT and the access is O(log n) - the “forking” factor of the maps is 32, so even very big maps are rather shallow and rarely involve more than 3 levels (32k items).
Anyway, maps are superior to me because of one simple thing - I can read them. Records are terrible in that regard - you get a tagged tuple and you have no idea what the fields mean. Debugging with records is a significantly worse experience and takes much longer. I would reach for records in the tightest loops of the program, where I need some “lolspeed”, but for everything else, maps and structs are plenty fast.
idi527
Also elixir code might be sometimes less efficient because of the way people write it and not due to the language itself.
- using string concatenation instead of iolists
- using structs instead of records
- accessing map elements via
.several times instead of a single pattern match - using
Keyword.fetchon every element in an “opts” list instead of iterating over it once - in general, trying to use elixir “imperatively” thus producing subpar code (many examples of this on this very forum)
benwilson512
Sure, let me make this a bit more concrete.
When you write literally the same code, you get literally the same bytecode. Examples:
-module(math).
-export([factorial/1]).
factorial(0) ->
1;
factorial(X) when X > 0 ->
X * factorial(X-1).
Will produce exactly the same bytecode as
defmodule Factorial do
def factorial(0), do: 1
def factorial(x) when x > 0, do: x * factorial(x - 1)
end
Literally 100% the same. Now, the Elixir standard library sometimes favors certain patterns of abstractions that provide a negligible, but not technically 0 cost compared to an erlang alternative. So for example:
Enum.map(list, fn x -> x * 2 end)
has 1 function call more over head (1 period, not 1 per item) than:
lists:map(fun(X) -> 2*X end, List).
because the Enum.map function will convert non list things to a list in order to map over them. If it is a list, it will just call that same function, which you can do yourself:
# this is elixir code
:lists.map(fn x -> x * 2 end, items)
and that ^ is again byte for byte identical with the erlang code.
So in terms of which one is faster, what it really boils down to is the approaches that each library takes. Certain things that Elixir macros let you do for example make certain high performance strategies a lot easier or more ergonomic than in erlang, and so it can actually be faster. Other times the desire to create friendly APIs in Elixir can sometimes introduce slightly more indirection, which can introduce small if technically non zero overhead.
Fundamentally though whether your Elixir code has overhead WRT erlang is entirely a question of what Elixir code you write. They compile to time same core structure, and end up as the same bytes.







