View Source Reginald

Reginald is a simple distributed registry built in pure Elixir on top of the built-in Erlang :pg module.

Motivations

I've recently started experimenting with distributed registries, after seeing various posts and examples of different Distributed Erlang/Elixir helpers, such as the built-in :global module, syn, and horde.

After reading a lot, I started benchmarking them in a similar way to what @ostinelli did almost a decade ago. The benchmarks can be seen here: probably-not/regbench. The benchmarks showed some drastically different details than what most people assume:

  • syn is very (and likely the best choice to be honest), at the expense of being written in Erlang as opposed to Elixir (which makes it more difficult to understand and debug for people who aren't familiar with Erlang)
  • :pg used to be slow back when it was first benchmarked by @ostinelli, however now it is blazing fast, at the level of syn. However, it isn't exactly a registry (although as you'll see with Reginald, it can easily be modified to be one)
  • :global is slow, but not unreasonable so (unless you are working with a gigantic amount of registrations per second)
  • :horde is by far the slowest, although for some reason people always immediately say "don't use global, use horde instead", which seems... insane to me... it doesn't look like there were any benchmarks between horde and any other option, but people immediately say to use it instead of anything else.

After doing these benchmarks, I decided that I wanted to build a Registry that would work with Distributed Elixir, and be written in pure Elixir, while being as fast as possible. The result is Reginald, your simple Distributed blazing-fast registry.

Usage

Reginald can be either started directly with Reginald.start_link/1 or started as part of a supervisor by adding {Reginald, name: MyApp.Reginald} to your supervision tree.

A :name option must be passed as the arguments to Reginald.start_link/1.

For usage as a Registry, simply use a via module like the following: {:via, Reginald, {MyApp.Reginald, "any id"}}, for example:

defmodule ExampleGenServer do
  use GenServer

  def start_link(id) do
    GenServer.start_link(__MODULE__, id, name: via_tuple(id))
  end

  def via_tuple(id) do
    {:via, Reginald, {MyApp.Reginald, id}}
  end

  def hello(id) do
    GenServer.cast(via_tuple(id), :hello)
  end

  @impl true
  def init(id) do
    {:ok, id}
  end

  @impl true
  def handle_cast(:hello, id) do
    IO.puts("Got Hello!")
    {:noreply, id}
  end
end

Installation

If available in Hex, the package can be installed by adding reginald to your list of dependencies in mix.exs:

def deps do
  [
    {:reginald, ">= 0.0.0"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/reginald.