Using Erlang Persistent Terms In Elixir
Published on 2021-03-20
5m read
programming, elixir, erlang, functional programming
Recently I learned about an erlang module introduced on OTP 21.2 called persistent_term
.
The module is similar to ets
, but it has been greatly optimized for reading speeds at the cost more expensive writes and updates to existing terms. Let’s take a quick look at an example of persistent_terms.
iex(1)> :persistent_term.info()
%{count: 11, memory: 1160}
iex(2)> :persistent_term.get()
[
{:logger_proxy, {:logger_proxy, #PID<0.73.0>, {:logger_olp, :logger_proxy}}},
{{:logger_config, {:"$handler_config$", Logger}}, 10},
{{:logger_olp, :logger_std_h_default}, :async},
{{:logger_config, :supervisor_bridge}, 7},
{:rex_nodes_observer, #Reference<0.4121486589.1675493377.224648>},
{{:logger_olp, :logger_proxy}, :async},
{{:logger_config, :supervisor}, 7},
{{:logger_config, :"$primary_config$"}, 7},
{{:logger_config, {:"$handler_config$", :simple}}, :undefined},
{{:logger_config, {:"$handler_config$", :default}}, :undefined},
{{:logger_config, :application_controller}, 7}
]
iex(3)> :persistent_term.put(:secret_configuration, [%{key: "value"}, %{key: "another value"}])
:ok
iex(4)> :persistent_term.get(:secret_configuration)
[%{key: "value"}, %{key: "another value"}]
iex(5)> :persistent_term.get()
[
{:logger_proxy, {:logger_proxy, #PID<0.73.0>, {:logger_olp, :logger_proxy}}},
{{:logger_config, {:"$handler_config$", Logger}}, 10},
{{:logger_olp, :logger_std_h_default}, :async},
{:secret_configuration, [%{key: "value"}, %{key: "another value"}]},
{{:logger_config, :supervisor_bridge}, 7},
{:rex_nodes_observer, #Reference<0.4121486589.1675493377.224648>},
{{:logger_olp, :logger_proxy}, :async},
{{:logger_config, :supervisor}, 7},
{{:logger_config, :"$primary_config$"}, 7},
{{:logger_config, {:"$handler_config$", :simple}}, :undefined},
{{:logger_config, {:"$handler_config$", :default}}, :undefined},
{{:logger_config, :application_controller}, 7}
]
Pros
- VM-wide storage, and accessible from any module.
- Optimized for read performance.
- Part of OTP no additional dependecies need
Cons
- Updates and inserts can be expensive
- No protection for naming collitions