Some complimentary information to @José answer:
process_dictionary is local, it dies with the process, cannot be accessed from external process
persistent_element is global, it dies only with the node. It can be accessed by any process, without control.
ETS is owned by a process, it can be shared by different processes, it dies with the owner, the ownership can be given away to another process, it offers some access control (public, private, protected) and different organization types and accesses.
a short session in the shell shows (most) of these differences.
12> persistent_term:put(global,value1).
ok
13> put(local,value2). % with process_dictionary, put returns the previous value associated to the key
undefined
14> ets:new(my_ets,[named_table,public]). % create a public table
my_ets
15> ets:insert(my_ets,{shared,value3,other_values}).
true
16> persistent_term:get(global). % check that everything is stored
value1
17> get(local).
value2
18> ets:lookup(my_ets,shared).
[{shared,value3,other_values}]
19> ets:lookup_element(my_ets,shared,2). % a small example of ETS extended capabilities
value3
20> F1 = fun(From) -> From ! persistent_term:get(global) end. % prepare the same functions to be executed from external process
#Fun<erl_eval.44.97283095>
21>
21> F2 = fun(From) -> From ! get(local) end.
#Fun<erl_eval.44.97283095>
22> F3 = fun(From) -> From ! ets:lookup(my_ets,shared) end.
#Fun<erl_eval.44.97283095>
23> Me = self().
<0.19320.1>
24> spawn(fun() -> F1(Me) end).
<0.12906.2>
25> flush(). % persistent_term are global
Shell got value1
ok
26> spawn(fun() -> F2(Me) end).
<0.13701.2>
27> flush(). % prrocess_dictionary is local
Shell got undefined
ok
28> spawn(fun() -> F3(Me) end).
<0.13968.2>
29> flush(). % ETS can be shared
Shell got [{shared,value3,other_values}]
ok
30> 1/0. % create an exception so the shell dies and is restarted by its supervisor
** exception error: an error occurred when evaluating an arithmetic expression
in operator '/'/2
called as 1 / 0
31> Me = self(). % the shell's Pid changed
** exception error: no match of right hand side value <0.14499.2>
32> persistent_term:get(global). % persistent are still there
value1
33> get(local). % Oooops! the process dictionary is still there too. Warning, this is a side effect of the shell implementation
value2
34> ets:lookup(my_ets,shared). % my_ets does not exist anymore
** exception error: bad argument
in function ets:lookup/2
called as ets:lookup(my_ets,shared)
35>