Sie sind auf Seite 1von 25

persistent_term

persistent_term 1
Hello

— Clark Kampfe
— Fast Radius
— 3D printing manufacturing
— Phoenix, Nerves in production
— Yes we're hiring

persistent_term 2
Problem

— Global data
— Big
— Lots of concurrent access
— Rarely changing

persistent_term 3
Examples

— Config data
— Cluster hosts
— Large precomputed math calculations

persistent_term 4
Solutions Elsewhere

— Locks (C, Java, etc.)


— Immutable persistent data structures (Clojure, etc)
— Compile-time ownership enforcement (Rust)

persistent_term 5
Elixir/Erlang VM: The BEAM

— Error handling with restarts/supervision


— Concurrency story
— Process GC is independent
— Everything is copied (some exceptions)

persistent_term 6
Solutions in Elixir/Erlang

— GenServer
— ETS
— FastGlobal
— persistent_term (new!)

persistent_term 7
GenServer

defmodule Pterm.MapServer do

use GenServer

# PUBLIC
######################################

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

def get(pid) do
GenServer.call(pid, :get, 30_000)
end

# CALLBACKS
######################################

def init(%{data: data} = _args) do


{:ok, data}
end

def handle_call(:get, _from, state) do


{:reply, state, state}
end
end

### Client

{:ok, server} = Pterm.MapServer.start_link(%{data: %{a: 1, b: 2}})


Pterm.MapServer.get(server) #=> %{a: 1, b: 2}

persistent_term 8
GenServer

— Like every other Erlang process


— Easy, not fast
— Idiomatic, battle-tested
— Built in
— Data is copied to caller: keyspace access patterns
matter!
— Process mailbox can bottleneck reads and writes

persistent_term 9
ETS - Erlang Term Storage

hosts = %{...}

:ets.new(:hosts, [{:read_concurrency, true}, :named_table])

:ets.insert(:hosts, {:hosts_data, big_hosts_data})

[{:hosts_data, data}] = :ets.lookup(:hosts, :hosts_data)

persistent_term 10
ETS - Erlang Term Storage

— Basically, Redis
— Big mutable hash table
— Easy, fast
— Built in
— Not GC'd
— Data is copied to caller: keyspace access patterns
matter!

persistent_term 11
FastGlobal

hosts = %{...}

FastGlobal.put(:hosts, hosts)

FastGlobal.get(:hosts)

persistent_term 12
FastGlobal

— Data is compiled into module constant


— Easy, fast
— Compilation slows down with data size
— Kind of a hack
— Updates require recompilation
— External library
— Data is not copied to caller

persistent_term 13
persistent_term

hosts = %{...}

:persistent_term.put({HostsModule, :hosts}, hosts)

:persistent_term.get({HostsModule, :hosts})

true = :persistent_term.erase({HostsModule, :hosts})

persistent_term 14
persistent_term

— new in OTP 21.2 (December 2018)


— Big mutable global hash table
— Easy, fast
— Not GC'd
— Built in
— Updates are very expensive
— Best for few, larger data
— Data is not copied to caller
persistent_term 15
persistent_term - Warning!

Persistent terms is an advanced feature and is not a general


replacement for ETS tables. Before using persistent terms,
make sure to fully understand the consequence to system
performance when updating or deleting persistent terms.
— the OTP gods

persistent_term 16
persistent_term considered dangerous

On term deletion or replacement...

All processes in the system will be scheduled to run a scan of


their heaps for the term that has been deleted. While such
scan is relatively light-weight, if there are many processes, the
system can become less responsive until all process have
scanned their heaps.
— the OTP gods

persistent_term 17
small, n = 10, parallelism = 6

persistent_term 18
medium, n = 10,000, parellelism = 6

persistent_term 19
large, n = 1,000,000, parallelism = 6

persistent_term 20
small, n = 1,000, parallelism = 60

persistent_term 21
medium, n = 10,000, parallelism = 60

persistent_term 22
large, n = 1,000,000, parallelism = 60

persistent_term 23
summary

### GenServer ETS FastGlobal persistent_term

difficulty easy easy easy easy

1 read perf medium fast fast very fast

1 write perf medium fast very slow very slow

many read perf slow fast fast very fast

many write perf slow fast very slow very slow

builtin? yes yes no yes

lookup anything hashtable hashtable hashtable

distributed can be no no no

persistent_term 24
persistent_term 25

Das könnte Ihnen auch gefallen