Erlang原子如何工作?

Bit*_*ler 7 erlang

试图找到有关细节的文档,我没有发现很多东西:

  • 有一个(erlang运行时实例 - )原子表.
  • Atom字符串文字只存储一次.
  • 原子需要1个字.

对我来说,这留下了许多不清楚的事情.

  1. 原子字值是否始终相同,与序列模块加载到运行时实例无关?如果模块A和B都定义/引用一些原子,那么原子的值会在会话之间发生变化,这取决于是先加载A还是B?

  2. 当匹配模块内的原子时,是否存在一些"原子文字到原子值"的分辨率?模块是否有一些自己的模块本地原子值查找表,它在模块的加载时填充?

  3. 在2个erlang运行时实例相互通信的分布式场景中.是否有一些"sync-atom-tables"动作正在进行?或者将原子序列化为字符串文字,而不是单词?

Gre*_*reg 11

Atom只是VM维护的ID.ID的表示是底层架构的机器整数,例如32位系统上的4个字节和64位系统上的8个字节.请参阅LYSE书中的用法.

同一个正在运行的VM中的同一个原子始终映射到相同的ID(整数).例如以下元组:

{apple, pear, cherry, apple}
Run Code Online (Sandbox Code Playgroud)

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

{1, 2, 3, 1}
Run Code Online (Sandbox Code Playgroud)

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

回答你的问题:

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

{50, 51, 52, 50}
Run Code Online (Sandbox Code Playgroud)

取决于在加载之前已创建的其他原子.原子只与VM一样长.

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

3.没有原子的表是每个VM,它们是分开的.考虑两个VM同时启动但彼此不了解的情况.在每个VM中创建的原子可能在表中具有不同的ID.如果在某个时间点,一个节点了解另一个节点,则不同的原子将具有不同的ID.它们不容易同步或合并.但原子不仅仅是作为文本表示发送到另一个节点.它们被"压缩"为一种缓存形式,并在标题中一起发送.请参阅通信协议说明中的分发标头.基本上,标题包含稍后使用的原子及其ID和文本表示.然后,每个术语通过标头中指定的ID引用atom,而不是每次都传递相同的文本.