Как сохранить состояние однократной записи на уровне модуля? - PullRequest
2 голосов
/ 26 мая 2020
• 1000 Каков эффективный и обычный способ сделать это?

Я мог бы создать функцию, которая всегда возвращает один и тот же набор:

my_set() -> sets:from_list(["a", "b", "c"]).

Будет ли это оптимизировать виртуальная машина или код для построения набор будет запускаться каждый раз заново? Я подозреваю, что набор просто получит GCd.

В этом случае должен ли я кэшировать набор в словаре процесса, используя что-то уникальное, например, модуль md5?

Key = proplists:get_value(md5, module_info()), put(Key, my_set())

Другое решение - заставить вызывающего абонента вызвать функцию init, чтобы вернуть непрозрачный кусок состояния, а затем передать это состояние каждой функции в модуле.

1 Ответ

6 голосов
/ 26 мая 2020

Константа времени компиляции, такая как ваш список примеров ["a", "b", "c"], будет храниться в пуле констант на стороне, когда модуль загружен, и не будет перестраиваться каждый раз при запуске выражения. (Раньше список восстанавливался из его элементов для каждого нового вызова.) Это касается всех констант, независимо от их сложности (например, списков списков кортежей). Но когда вы вызываете такую ​​функцию, как sets: from_list / 1, компилятор не может ничего предположить о представлении, используемом модулем sets, и набор будет создаваться динамически из этого списка констант. таблица будет работать, она менее эффективна для больших констант (например, набора или карты, содержащей много записей), потому что таблица ETS имеет ту же модель памяти, что и процесс - данные записываются и читаются путем копирования, как если бы при отправке Сообщения. Если константы маленькие, разница между их копированием и локальным воссозданием будет незначительной, а если константы большие, вы тратите время на их копирование.

Вместо этого вам нужна довольно новая функция, называемая Persistent Term Хранилище: https://erlang.org/doc/man/persistent_term.html (начиная с Erlang / OTP 21). Это похоже на способ обработки констант времени компиляции, поэтому при поиске значения не происходит копирования. (Ключом может быть имя вашего модуля.) Постоянный термин предназначен в значительной степени как хранилище с однократной записью и многократным чтением - вы можете обновить сохраненную запись, но это более дорогостоящая операция, которая может вызвать глобальный G C.

...