I’m just back from giving a training at ElixirConf EU about advanced concurrency patterns in Elixir. I love Erlang’s process model to death. But I also love the things that the OTP team shipped in the past few years focused on essentially escaping that model.
Many languages seem to start from mutable, fast data structures and then build concurrency features, thread isolation, all that. Erlang went the opposite direction. Start with concurrency primitives, immutable data, per-process memory. Then, introduce escape hatches that let processes pry into shared areas of memory and (safely!) modify them.
ETS is the one everybody knows and reaches for when needing a form of somewhat-mutable, shared memory space. In recent OTP releases, however, we got a few wonderful additions to our toolbox. We’ll focus on the ones for counting stuff: :atomics and :counters .
:atomics
An atomics array is an off-heap, shared, mutable block of N × 64-bit integers (signed or unsigned). That’s a mouthful. To break it down:
Off-heap : it doesn’t live in the heap of a process. It lives in a magical place somewhere in the BEAM.
: it doesn’t live in the heap of a process. It lives in a magical place somewhere in the BEAM. Shared : no process owns it—the BEAM does.
: no process owns it—the BEAM does. Mutable: when you update this lil’ data structure, you actually change the bytes in memory, as opposed to updating Erlang/Elixir data structures (which copies them because they’re immutable).
The “array” part means that whenever you create a “ :atomics data structure”, you’re creating an array of n n n integers:
Create such a data structure and mess around with it:
... continue reading