erlang中的原子(atom)内部实现

Erlang中的atom由通用hash表实现,虚拟机中atom最终的用数值表示,对应表中的下标值。本文通过list_to_atom函数的实现,分析atom在虚拟机中的内部实现。先看atom的数据结构:

再看IndexSlot结构体,它是一个通用的结构:

HashBucket定义

直观表示为:
|———————— Atom ————————|
|—— IndexSlot ——|
|— HashBacket —|
Atom结构体的头部为 IndexSlot, IndexSlot的头部则为 HashBacket。这样定义目的是为方便做指针类型转,指向Atom的指针可以转为 IndexSlot、HashBacket。在虚拟机中index table,hash table都写成为工具函数,给不同的应用。

atom最终保存中erts_atom_table全局变量中,erts_atom_table为IndexTable结构体。IndexTable结构体定义:

Hash结构体定义:

erts_index_table简单结构图:
atom

atom的结构体介绍完,直接看 list_to_atom的bif实现。

再看erts_atom_put的实现,函数会先检查atom是否在index_table中,如果已经存在则返回,否则添加新atom到index_table。

index_put函数在index.h中定义,这里 tmpl传入类型为 atom

index_put_entry函数,调用hash_put接口,返回的值为Atom结构体,因为IndexSlot,HashButket 都定义在头部,所以可以对指针类型进程转换。如果在返回的IndexSlot->index不少于0(新atom中,index初始化为-1),则atom已经在hash表中,否则把atom加入seg_table,atom数entries++。

再看hash_put,上面已经说过,Hash->bucket是个一维数据,元素为单向链表。通过fun.hash得到的相同 hash值的元素将放在同一链表中。当bucket中的slot使用量达到80%时,会重新扩充hash表。

由可以看到,atom的值其实是index talbe中的下标,再通过make_atom/1转换得到,它最终是一个整数值。函数make_atom做的工作是向右移位,再在低位中加入atom的标签。如果atom已经在erts_index_table中,则不会再添加新值,直接返回。所以对于list_to_atom之前,要先调用list_to_existing_atom来复用atom来防止atom超出上限的说法,其实是多余的。

Erlang技术分享内容均为原创,转载请标明本文地址
本文链接:http://www.kongqingquan.com/archives/208

此条目发表在erts内核分类目录,贴了, , , , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">