Hmm, don’t know, let’s test, I whipped up a simple benchmark between persistent_term, ets, and head dispatch (which is how protocols dispatch), using 1000 trivial entries of ints and 1000 entries of 32-byte binaries, the source:
defmodule BenchDefs do
def range(:ints), do: 1..1000
def range(:binaries32),
do: unquote(Enum.map(1..1000, fn _ -> :crypto.strong_rand_bytes(32) end))
end
defmodule HeadDispatch do
for i <- [BenchDefs.range(:binaries32), BenchDefs.range(:ints)], j <- i do
def match(unquote(j)), do: unquote(j)
end
end
defmodule PersistentTermBench do
def classifiers(), do: [:ints, :binaries32]
def time(_), do: 2
def inputs(cla),
do: %{
"First" => BenchDefs.range(cla) |> Enum.into([]) |> List.last(),
"Last" => BenchDefs.range(cla) |> Enum.into([]) |> List.last()
}
def setup(cla) do
Enum.each(BenchDefs.range(cla), &:persistent_term.put(&1, &1))
tab = :ets.new(PersistentTermBench, [])
Enum.each(BenchDefs.range(cla), &:ets.insert_new(tab, {&1}))
tab
end
def teardown(_, tab) do
:ets.delete(tab)
end
def actions(_, tab),
do: %{
":persistent_term" => fn inp -> :persistent_term.get(inp) end,
":ets" => fn inp -> :ets.lookup(tab, inp) end,
"HeadDispatch" => fn inp -> HeadDispatch.match(inp) end
}
end
And the results:
Benchmarking Classifier: ints
=============================
Operating System: Linux"
CPU Information: AMD Phenom(tm) II X6 1090T Processor
Number of Available Cores: 6
Available memory: 15.67 GB
Elixir 1.7.4
Erlang 21.2
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 2 s
memory time: 2 s
parallel: 1
inputs: First, Last
Estimated total run time: 36 s
Benchmarking :ets with input First...
Benchmarking :ets with input Last...
Benchmarking :persistent_term with input First...
Benchmarking :persistent_term with input Last...
Benchmarking HeadDispatch with input First...
Benchmarking HeadDispatch with input Last...
##### With input First #####
Name ips average deviation median 99th %
HeadDispatch 22.21 M 0.0450 μs ±6.97% 0.0440 μs 0.0540 μs
:persistent_term 15.28 M 0.0655 μs ±3.23% 0.0650 μs 0.0740 μs
:ets 8.07 M 0.124 μs ±172.07% 0.120 μs 0.180 μs
Comparison:
HeadDispatch 22.21 M
:persistent_term 15.28 M - 1.45x slower
:ets 8.07 M - 2.75x slower
Memory usage statistics:
Name Memory usage
HeadDispatch 136 B
:persistent_term 136 B - 1.00x memory usage
:ets 200 B - 1.47x memory usage
**All measurements for memory usage were the same**
##### With input Last #####
Name ips average deviation median 99th %
HeadDispatch 22.38 M 0.0447 μs ±6.12% 0.0440 μs 0.0530 μs
:persistent_term 15.21 M 0.0658 μs ±7.30% 0.0650 μs 0.0750 μs
:ets 8.08 M 0.124 μs ±143.17% 0.120 μs 0.180 μs
Comparison:
HeadDispatch 22.38 M
:persistent_term 15.21 M - 1.47x slower
:ets 8.08 M - 2.77x slower
Memory usage statistics:
Name Memory usage
HeadDispatch 136 B
:persistent_term 136 B - 1.00x memory usage
:ets 200 B - 1.47x memory usage
**All measurements for memory usage were the same**
Benchmarking Classifier: binaries32
===================================
Operating System: Linux"
CPU Information: AMD Phenom(tm) II X6 1090T Processor
Number of Available Cores: 6
Available memory: 15.67 GB
Elixir 1.7.4
Erlang 21.2
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 2 s
memory time: 2 s
parallel: 1
inputs: First, Last
Estimated total run time: 36 s
Benchmarking :ets with input First...
Benchmarking :ets with input Last...
Benchmarking :persistent_term with input First...
Benchmarking :persistent_term with input Last...
Benchmarking HeadDispatch with input First...
Benchmarking HeadDispatch with input Last...
##### With input First #####
Name ips average deviation median 99th %
HeadDispatch 10.98 M 0.0911 μs ±271.68% 0.0800 μs 0.180 μs
:persistent_term 8.17 M 0.122 μs ±240.94% 0.120 μs 0.180 μs
:ets 4.74 M 0.21 μs ±85.30% 0.20 μs 0.31 μs
Comparison:
HeadDispatch 10.98 M
:persistent_term 8.17 M - 1.34x slower
:ets 4.74 M - 2.32x slower
Memory usage statistics:
Name Memory usage
HeadDispatch 184 B
:persistent_term 136 B - 0.74x memory usage
:ets 248 B - 1.35x memory usage
**All measurements for memory usage were the same**
##### With input Last #####
Name ips average deviation median 99th %
HeadDispatch 10.86 M 0.0921 μs ±481.96% 0.0900 μs 0.170 μs
:persistent_term 8.10 M 0.123 μs ±254.71% 0.120 μs 0.180 μs
:ets 4.79 M 0.21 μs ±72.56% 0.20 μs 0.30 μs
Comparison:
HeadDispatch 10.86 M
:persistent_term 8.10 M - 1.34x slower
:ets 4.79 M - 2.27x slower
Memory usage statistics:
Name Memory usage
HeadDispatch 184 B
:persistent_term 136 B - 0.74x memory usage
:ets 248 B - 1.35x memory usage
**All measurements for memory usage were the same**
So interned head matchers are still the fastest, barely, followed closely by persistent_term, with ETS over 2 times slower after that. So keeping protocols as head matchers is still fastest.
I’d say keep it as functions in a module.
Thus no.