我如何存储模块级一次写入状态?

问题描述 投票:2回答:1

我有一些模块级别的状态,我想只写一次,然后再不修改。

具体地说,我有一组字符串,我想在以后使用它们来查找内容。什么是有效的普通方法?

我可以创建一个始终返回相同集合的函数:

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

VM将对此进行优化,还是会每次重新运行用于构建集合的代码?我怀疑该集合只会得到GCd。

在那种情况下,我应该将集合缓存在进程字典中,并以诸如md5模块之类的独特内容为键吗?

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

另一种解决方案是使调用方调用init函数以获取不透明的状态块,然后将该状态传递到模块中的每个函数中。

caching erlang
1个回答
6
投票

一个编译时常量,如您的示例列表["a", "b", "c"],将在模块加载时存储在侧面的常量池中,并且不会在每次运行表达式时重新构建。 (过去,该列表是根据每个新调用的元素重新构造的。​​)无论常量多么复杂,它都适用于所有常量(例如元组列表)。但是,当您调用诸如sets:from_list / 1之类的函数时,编译器无法假定有关sets模块使用的表示形式的任何信息,并且set将根据该常量列表动态构建。

虽然ETS表可以工作,但是对于较大的常量(例如包含许多条目的集合或映射),效率较低,因为ETS表与进程具有相同的内存模型-通过复制来写入和读取数据,就像通过发送消息一样。如果常量很小,则复制常量和在本地重新创建常量之间的差异可以忽略不计;如果常量很大,则浪费时间复制它们。

您想要的是一个名为Persistent Term Storage:https://erlang.org/doc/man/persistent_term.html的相当新的功能(自Erlang / OTP 21起)。它类似于处理编译时间常数的方式,因此在查找值时不会进行复制。 (键可以是模块的名称。)Persistent Term的意思是一次写入多次读取多次存储-您可以更新存储的条目,但这是一个更昂贵的操作,可能会触发全局GC。 >

© www.soinside.com 2019 - 2024. All rights reserved.