Я знаю, что есть (по крайней мере) три способа создания изменяемого состояния в Erlang:

  • Таблицы ETS
  • persistent_term
  • Процессные словари

Основное их использование мне очень похоже:

% ETS
1> ets:new(table1, [named_table]).
2> ets:insert(table1, {thing}).
3> ets:lookup(table1, thing).
[{thing}]

% persistent_term
1> persistent_term:put(table2, thing).
2> persistent_term:get(table2).
thing

% Process dictionary
1> put(table3, thing).
2> get(table3).       
thing

Каковы различия и плюсы / минусы используют один над другим?

Я вижу, что ETS ведет себя больше как карта, но чем она отличается от хранения карт в persistent_term или словарях процессов?

1
radrow 15 Янв 2021 в 14:34

2 ответа

Лучший ответ

persistent_term и ets предоставляют похожий API, но они разные, я процитирую руководство:

Постоянные термины - это расширенная функция, которая не является общей заменой таблиц ETS.

persistent_term и {{x1}}} выставляют подобное API, но они разные, я процитирую

José M 15 Янв 2021 в 12:16

Некоторая дополнительная информация к ответу @ José:

Process_Dictictionary является локальным, он умирает с процессом, не может быть доступен из внешнего процесса

Persistent_element глобален, умирает только с узлом. Доступ к нему может получить любой процесс без контроля.

ETS принадлежит процессу, его можно поделиться различными процессами, он умирает с владельцем, владелец может быть отдан в другой процесс, он предлагает некоторый контроль доступа (публичные, частные, защищенные) и различные типы организаций и доступ.

Короткий сеанс в оболочке показывает (большинство) этих различий.

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> 
2
Pascal 15 Янв 2021 в 18:07