by Stephen Ball

Stephen’s Strange Leaflet about Elixir - Page 2

If you like there’s a Livebook version of this post where you can actually run code and follow along. This was written to be a Livebook first, but works well enough as a post too.


Well the BEAM is what gives Erlang its power.

The BEAM is the Erlang VM and it is a huge part of what make Erlang (and hence Elixir) special.


Erlang and Elixir are not competitors, they aren’t locked in a bitter struggle to establish dominance. Both languages run on the Erlang VM (BEAM) and can call each other completely transparently.

Let me show you some Erlang being called from some Elixir.


That sleep is the same as this Elixir code.


:timer is an Erlang module. That’s right to call Erlang from Elixir you just call the functions there’s no magic involved except the magic of the BEAM.

So the BEAM

Yes the BEAM!

Let’s start up an Elixir runtime and see what goes on here.

First: beam

The beam command starts in a single operating system process.

It’s important to understand that your operating system has processes but those are entirely different than Elixir processes.

{stdout, exitcode} = System.cmd("pgrep", ["-f", "beam.smp"])

beam_operating_system_process_ids = String.split(stdout, "\n", trim: true)

|> os_pid ->
  {stdout, 0} = System.cmd("ps", [os_pid, "-o", "pid=,command="])
|> Enum.join("\n")

If you were running this in Livebook you’d be able to see a cool live output of those system commands right in the Livebook but you aren’t so here.

$ pgrep -f beam.smp | xargs -L 1 ps -o pid=,command= | awk '{print $0 "\n"}'

That shell command will print out any commands with beam.smp in the command which is the Erlang BEAM VM command. The awk bit will put newlines between the lines which can be quite verbose e.g.

14966 /opt/homebrew/Cellar/erlang/24.3.2/lib/erlang/erts-12.3/bin/beam.smp --
-root /opt/homebrew/Cellar/erlang/24.3.2/lib/erlang -progname erl -- -home
/Users/sdball -- -pa /opt/homebrew/Cellar/elixir/1.13.3/bin/../lib/eex/ebin
/opt/homebrew/Cellar/elixir/1.13.3/bin/../lib/mix/ebin -elixir ansi_enabled
true -noshell -s elixir start_cli -extra /opt/homebrew/bin/mix phx.server

What we can see from that output is the beam commands running on your system. Or at least running on the system running this Livebook. (But you aren’t running this Livebook so, uh, that’s what it would be showing.)

BEAM stands for Bogdan/Björn’s Erlang Abstract Machine, which is the virtual machine at the core of the Erlang Open Telecom Platform (OTP).

When the beam command runs it starts the Erlang VM. Not a VM like a VMWare Fusion or VirtualBox VM: but a VM in a sense that it is a virtual machine that Elixir code talks to which abstracts away the actual machine that the beam is running on.

When it starts up, BEAM creates a thread for each CPU.

Each threads runs a scheduler that is responsible for, well, scheduling processes (now we’re talking about Elixir processes) to run.

Let’s stop for a second and think about that. This is the magic that allows Elixir systems to be highly scalable. Typical (well designed!) Elixir systems have thousands to millions of processes. Due to the nature of HOW BEAM WORKS FUNDAMENTALLY those processes are scheduled across ALL the CPUs available on your system.

That means as an Elixir programmer you essentially get scalable performance for free. You don’t have to think about how to design your threads and locks and waits: you write your processes that send messages to each other and BEAM spreads them around all the CPUs it can find.

What is Elixir? Elixir is beam running a thread per CPU running a scheduler per thread pulling Elixir processes off a queue for some time to run on the CPU.

Everything in Elixir is running in a process.

Elixir applications run thousands or millions of processes. Think of them as cheap as instantiating an object in an object oriented language.

« back to page 1 || turn to page 3 »


June 13, 2022