Skip to content

0.4 Physical modeling

Jean Chassoul edited this page Apr 18, 2021 · 2 revisions

Physical modeling

BEAM virtual machine

The BEAM virtual machine runs as one OS process. By default it runs one OS thread per core to achieve maximum utilization of the machine. The number of threads and on which cores they run can be set when the BEAM is started.

Erlang processes are implemented entirely by the VM and have no connection to either OS processes or OS threads. So even if you are running a BEAM system of over one million processes it is still only one OS process and one thread per core, in this sense the BEAM is a "process virtual machine" while the Erlang system itself very much behaves like an OS and Erlang processes have very similar properties to OS processes.

  • Process isolation
  • Asynchronous communication
  • Error handling, introspection and monitoring
  • Predefined set of datatypes
  • Immutable data
  • Pattern matching
  • Functional, soft real-time, reactive, message-passing system
  • Modules as function containers and the only way of handle code

Inside the BEAM ecosystem, we just worry about receiving messages.

Let it crash!

Robust systems must always be aware of errors but avoid the need of error checking code everywhere.

We want to be able to handle processes crashes among cooperative processes.

  • If one process crashes all cooperating processes should crash
  • Cooperating processes are linked together
  • Process crashes propagate along links

System processes can monitor them and rest them when necessary but sometimes we do need to handle errors locally.

Pattern matching

Functions use pattern matching to select clauses, this is a BIG WIN™

Supervision trees

A supervisor has a standard set of interface functions and include functionality for tracing and error reporting. Supervisors are used to build a hierarchical process structure called a supervision tree, a nice way to structure a fault-tolerant application.

  • Supervisors will monitor their processes through links and trapping exists.
  • Supervisors can restart the workers when they terminate.

On production, this usually means a fairly straight-forward combination of external process management, overload monitoring and proxying.

A supervisor is responsible for starting, stopping, and monitoring external processes. The basic idea of a supervisor is that it is to keep its processes alive by restarting them when necessary.

Fault-tolerance

Fault-tolerance is achieved by creating supervision trees, where the supervisors are the nodes and the workers are the leaves of this analogy. Supervisors on a particular level monitor and handle children in the subtrees they have started.

If any worker terminates abnormally, the simple supervisor immediately restart it. If the process instead terminate normally, they are removed from the supervision tree and no further action is taken.

Stopping the supervisor results in all the processes in the tree being unconditionally terminated. When the supervisor terminates, the run-time ensures that all processes linked to it receive an EXIT signal.

It is a valid assumption that nothing abnormal should happen when starting your system.

If a supervisor is unable to correctly start a process, it terminates all of its processes and aborts the startup procedure.

While we are all for a resilient system that tries to recover from errors, startup failures is where we draw the line.

Load balancing

Compacting the load to fewer schedulers is usually better for memory locality, specially on hyperthreads, the primary process is in charge of balance the rest of the schedulers. The goal is to not overload any scheduler while using as little CPU as possible.

Process stealing

Used by artists of all types and computers alike, on the BEAM is the primary mechanism to load balance and spread processes.

  • A scheduler with nothing runnable will try to "steal processes" from adjacent schedulers, then next beyond that.
  • We only steal from run-queues, never running or suspended processes.
  • Schedulers changes on other schedulers run-queues.
  • Each scheduler has its own run-queue.
  • Processes suspend when waiting for messages, this is NOT a busy wait.
  • Suspended processes become runnable when a message arrives.

By this mechanism the BEAM suspend unneeded schedulers. Once every period of 20k function calls is reach a new primary process inside a node scheduler is chosen.