【问题标题】:How do Erlang atoms work?Erlang 原子是如何工作的?
【发布时间】:2016-07-01 15:22:18
【问题描述】:

试图查找有关详细信息的文档,但我没有找到很多其他内容:

  • 有一个(erlang 运行时实例-)原子表。
  • Atom 字符串文字只存储一次。
  • 原子占用 1 个单词。

对我来说,这留下了很多不清楚的地方。

  1. 原子单词值是否始终相同,独立于将模块加载到运行时实例中的顺序?如果模块 A 和 B 都定义/引用了一些原子,原子的值会随着会话的不同而变化,这取决于是先加载 A 还是 B?

  2. 当匹配模块内的原子时,是否会发生一些“原子文字到原子值”的解析?模块是否有一些自己的模块本地原子值查找表,在模块加载时填充?

  3. 在 2 个 erlang 运行时实例相互通信的分布式场景中。是否正在进行一些“同步原子表”操作?还是原子被序列化为字符串文字,而不是单词?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    Atom 只是一个由 VM 维护的 ID。 ID 的表示是底层架构的机器整数,例如在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节。用法见LYSE book。

    同一运行 VM 中的同一原子始终映射到同一 ID(整数)。例如下面的元组:

    {apple, pear, cherry, apple}
    

    可以在实际的 Erlang 内存中存储为以下元组:

    {1, 2, 3, 1}
    

    所有原子都存储在一个永远不会被垃圾回收的大表中,即,一旦在正在运行的 VM 中创建了原子,它就会一直保留在表中,直到 VM 关闭。

    回答您的问题:

    1 . 不会。原子的 ID 将在 VM 运行之间发生变化。如果您关闭 VM 并重新加载系统上方的元组,则最终可能会得到以下 ID:

    {50, 51, 52, 50}
    

    取决于在加载之前创建了哪些其他原子。原子的寿命与虚拟机一样长。

    2 . 不,每个虚拟机只有一张原子表。加载模块时,模块中的所有文字原子都映射到它们的 ID。如果该表中尚不存在特定原子,则将其插入并保留在那里,直到 VM 重新启动。

    3 . 不。带有原子的表是每个 VM 的,它们是独立的。考虑两个虚拟机同时启动但彼此不知道的情况。在每个 VM 中创建的原子在表中可能具有不同的 ID。如果在某个时间点一个节点了解另一个节点,不同的原子将具有不同的 ID。它们不能轻易同步或合并。但是原子也不是简单地作为文本表示形式发送到另一个节点。它们被“压缩”为一种缓存形式,并在标头中一起发送。参见通信协议描述中的distribution header。基本上,标头包含稍后使用的原子及其 ID 和文本表示。然后每个术语通过标头中指定的 ID 引用原子,而不是每次都传递相同的文本。

    【讨论】:

    • 对于已经存在于 vm 中并且也包含在分发标头中的具有不同值的原子会发生什么?
    • 分发标头中的 ID 仅为特定通信目的而创建。这是一种通信协议,因此这些 ID 独立于存储在 VM 原子表中的 ID。假设“苹果”存储在原子表中时的 ID 为 5,然后在通信中发送时说它存储在分发标头中时的 ID 为 14。然后,当原子到达另一个节点时,另一个 VM 在其原子表中查找该原子的文本表示,并将其与原子表中的 ID 一起存储,例如 43。
    • @BitTickler 回复。传输中的原子:根据Erlang external term format,它们被序列化为二进制字符串。这就是term_to_binary/1 和binary_to_term/1,2 所做的。例如,字符串“foo”是列表[102,111,111]。作为外部术语“foo”,以下是正确的:<<131,107,0,3,102,111,111>> = term_to_binary("foo"). 现在比较:<<131,119,3,102,111,111>> = term_to_binary(foo). 但这是外部。在内部,它们与 Amiramix 所说的完全一样:引用标签到整数常量(巨大 性能增强)。
    【解决方案2】:

    为了在不进入实现的情况下获得真正的基础,原子是一个带有名称的字面“事物”。它的价值永远是它自己,它知道自己的名字。您通常在需要标签时使用它,例如原子ok 和error。原子是唯一的,因为系统中只有一个原子foo,每次我提到foo,我指的是同一个唯一的foo,无论它们是否在同一个模块中,或者它们是否来自同一个过程。 foo 永远只有一个。

    一点实现。原子存储在一个全局原子表中,当你创建一个新原子时,如果它不存在,它会被插入到表中。这使得比较原子的相等性非常快,因为您只需检查两个原子是否引用原子表中的同一个槽。

    虽然虚拟机的独立实例 nodes 具有独立的 atom 表,但分布式 erlang 中节点之间的通信为此进行了优化,因此您通常不需要发送实际的 atom节点之间的名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 2012-06-09
      • 2016-07-12
      • 1970-01-01
      • 2015-04-19
      • 2013-12-29
      相关资源
      最近更新 更多