Erlang Binary的内部结构和分类介绍
来源:互联网 发布:淘宝宝贝标题关键词 编辑:程序博客网 时间:2024/05/16 06:39
我们先来重温一下《Erlang数据类型的内部实现》一文。
Type Name Header Tag (B) Tag Name #define SUBTAG refc binaries 1000REFC_BINARYREFC_BINARY_SUBTAGheap binaries 1001HEAP_BINARYHEAP_BINARY_SUBTAGsub binary 1010SUB_BINARYSUB_BINARY_SUBTAGmatch context 0001BINARY_AGGREGATEBIN_MATCHSTATE_SUBTAG
引用计数二进制可由以下两个结构体组合起来描述:
引用计数二进制包含两部分:
堆二进制是最大为64字节的小二进制,它被直接存储在进程堆里。对于堆二进制,当GC或被作为消息发送时,它会被复制,在GC方面不需要做特别的处理。
子二进制是在使用函数split_binary/2或进行二进制匹配时产生的。它可以引用现有的refc binary或heap binary的一部分。充分使用子二制这一特性,可以提升二进制匹配操作的性能,因为匹配结果不用从原二进制中拷贝。
match context和子二进制类似。为了匹配操作可以更快速,对比于子二进制,它做了一些优化,增加了直接指向二进制数据的指针(ErlBinMatchState->mb->base),当从二进制数据中匹配出字段值后直接移动指针即可。
sub binary和match context是对refc或heap二进制数据中某部分的描述,或者说是引用。
Erlang中封装binary数据指针时,尾部都会被贴上boxed标签(即最后2位为10B),
指针所指向的内容首4字节(确切的说是sizeof(Eterm)字节)是一个header,
从《Erlang数据类型的内部实现》一文中关于header的一段注释中可以看到:
/* * HEADER representation: * *aaaaaaaaaaaaaaaaaaaaaaaaaatttt00arity:26, tag:4 * * HEADER tags: * * 0001 BINARY_AGGREGATE | *1000REFC_BINARY| | *1001HEAP_BINARY| BINARIES| *1010SUB_BINARY| | * */#define BIN_MATCHSTATE_SUBTAG (0x1 << _TAG_PRIMARY_SIZE)#define _BINARY_XXX_MASK (0x3 << _TAG_PRIMARY_SIZE) #define REFC_BINARY_SUBTAG (0x8 << _TAG_PRIMARY_SIZE) /* BINARY */ #define HEAP_BINARY_SUBTAG (0x9 << _TAG_PRIMARY_SIZE) /* BINARY */ #define SUB_BINARY_SUBTAG (0xA << _TAG_PRIMARY_SIZE) /* BINARY */
从上面header可得知二进制数据在底层可以分为四类。
表1:Erlang Binary的四种类型
refc binaries (reference-counted binaries) 引用计数二进制
引用计数二进制可由以下两个结构体组合起来描述:
typedef struct proc_bin { Eterm thing_word;/* Subtag REFC_BINARY_SUBTAG. */ Uint size;/* Binary size in bytes. */ struct erl_off_heap_header *next; Binary *val;/* 指向Binary结构 */ byte *bytes;/* Pointer to the actual data bytes. */ Uint flags;/* Flag word. */} ProcBin;typedef struct binary { UWord flags; erts_refc_t refc; /* 引用计数 */ ERTS_BINARY_STRUCT_ALIGNMENT SWord orig_size; char orig_bytes[1]; /* to be continued */ // 作为二进制数据的容器1,这里会被动态扩展后继的内存空间} Binary;
引用计数二进制包含两部分:
- ProcBin,它被保存在进程堆里,ProcBin->val指向Binary。所有的ProcBin都是同一个链表的一部分,GC可以跟踪它们,当ProcBin移除时Binary->refc引用计数会减一。
- Binary,它徘徊在所有的进程堆之外,可被N个ProcBin引用,Binary->refc保存了引用计数,当引用计数为0时它将被抛弃。
heap binary 堆二进制
typedef struct erl_heap_bin { Eterm thing_word;/* Subtag HEAP_BINARY_SUBTAG. */ Uint size;/* Binary size in bytes. */ Eterm data[1];/* The data in the binary. */ // 作为二进制数据的容器2,这里会被动态扩展后继的内存空间} ErlHeapBin;
堆二进制是最大为64字节的小二进制,它被直接存储在进程堆里。对于堆二进制,当GC或被作为消息发送时,它会被复制,在GC方面不需要做特别的处理。
sub binary 子二进制
顾名思义,它就是用来描述现有二制进的某一部分的。
typedef struct erl_sub_bin { Eterm thing_word;/* Subtag SUB_BINARY_SUBTAG. */ Uint size;/* Binary size in bytes. */ Uint offs;/* Offset into original binary. */ byte bitsize; byte bitoffs; byte is_writable;/* The underlying binary is writable */ Eterm orig;/* Original binary (REFC or HEAP binary). */} ErlSubBin;
子二进制是在使用函数split_binary/2或进行二进制匹配时产生的。它可以引用现有的refc binary或heap binary的一部分。充分使用子二制这一特性,可以提升二进制匹配操作的性能,因为匹配结果不用从原二进制中拷贝。
match context
对于这个官方名字,有点纠结,想不到合适的中文名来描述它。在源码中没有看到这个名字的出现,在表1中可以看到与此名字对应的其它描述。
// This structure represents a binary to be matched.typedef struct erl_bin_match_buffer { Eterm orig;/* 指向原始二进制数据包(ProcBin或ErlHeapBin) */ byte* base;/* 直接指向二进制数据(ProcBin->bytes或ErlHeapBin->data) */ Uint offset;/* Offset in bits. */ size_t size;/* Size of binary in bits. */} ErlBinMatchBuffer;typedef struct erl_bin_match_struct{ // header(thing_word)的求值过程为: // (size << 6) | (TAG_PRIMARY_HEADER | BIN_MATCHSTATE_SUBTAG) Eterm thing_word; ErlBinMatchBuffer mb;/* Present match buffer */ Eterm save_offset[1];/* Saved offsets */} ErlBinMatchState;
match context和子二进制类似。为了匹配操作可以更快速,对比于子二进制,它做了一些优化,增加了直接指向二进制数据的指针(ErlBinMatchState->mb->base),当从二进制数据中匹配出字段值后直接移动指针即可。
小结
refc binaries和heap binaries是装二进制数据的容器。sub binary和match context是对refc或heap二进制数据中某部分的描述,或者说是引用。
- Erlang Binary的内部结构和分类介绍
- 关于erlang的binary
- 关于Erlang的binary
- 关于erlang的binary
- 关于erlang的binary
- [Erlang 0032] Erlang Binary的内部实现
- Set和Map的内部结构
- Set和Map的内部结构
- Set和Map的内部结构
- 简要介绍分布式服务器系统的内部结构
- 简要介绍分布式服务器系统的内部结构
- 简要介绍分布式服务器系统的内部结构
- Erlang学习:介绍Erlang里的Record
- erlang 中的 binary 和 binstring类型
- [Erlang]Binary结构和性能分析
- Windows Mobile 编译的内部结构和步骤
- 计算机的内部结构和启动过程剖析
- JVM的内部结构和启动流程
- 《MFC游戏开发》笔记二 建立工程、调整窗口
- Ext.Ajax.request与form.getForm().submit的区别
- poj2486 Apple Tree (树形dp)
- IPB帧编码顺序(解码顺序)与显示顺序
- 揭开linux内核中container_of的神秘面纱
- Erlang Binary的内部结构和分类介绍
- PRVF-00002: Could not retrieve local nodename
- 自由动态配置grid 表头,样式和数据
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- 【ExtJS】终极UI-CRUD、报表、导入、导出、数据模板式导入数据
- Ubuntu小私房(3)--Grub,Burg 的使用
- 随手在网上找了一段将字节数组转换为十六进制字符串的代码,结果被坑惨了
- 《Windows核心编程》阅读小记 1
- apache部署