dlmalloc解析连载三

上一篇讨论了dlmalloc大小在256字节以下的chunk块进行的组织管理,本篇我们再来看看对于大小在256字节以上的chunk块,dlmalloc是如何管理的。

对于大小在256字节以上的chunk块,dlmalloc也采用了所谓的分箱机制,不过由于大于256的数目有很多,因此这里的分箱不能够像对于0256这个有限区间的分箱来得简单。具体来说如下表:

字节范围

范围大小

箱号

[256, 384)

128

0

[384, 512)

128

1

[512, 768)

256

2

[768, 1024)

256

3

[1024, 1536)

512

4

[1536, 2048)

512

5

[2048, 3072)

1024

6

[3072, 4096)

1024

7

[4096, 6144)

2048

8

[6144, 8192)

2048

9

[8192, 12288)

4096

10

[12288, 16384)

4096

11

[16384, 24576)

8192

12

[24576, 32768)

8192

13

[32768, 49152)

16384

14

[49152, 65536)

16384

15

[65536, 98304)

32768

16

[98304, 131072)

32768

17

[131072, 196608)

65536

18

[196608, 262144)

65536

19

[262144, 393216)

131072

20

[393216, 524288)

131072

21

[524288, 786432)

262144

22

[786432, 1048576)

262144

23

[1048576, 1572864)

524288

24

[1572864, 2097152)

524288

25

[2097152, 3145728)

1048576

26

[4194304, 4194304)

1048576

27

[4194304, 6291456)

2097152

28

[6291456, 8388608)

2097152

29

[8388608, 12582912)

4194304

30

[12582912, 理论上无穷大)

理论上无穷大

31

 

这个表格里的数字是我先用程序打印出来然后再拷贝过来的,先简单解释一下,第一列“字节范围”表示大小在该范围内chunk块被分配到改行对应的第三列“箱号”所指定的箱子内。第二列表示第一列“字节范围”的范围大小,各位可以看到它们很有规律,在后面我们会讲到这种规律性的作用,因此这里也就先给出来。另外,这种规律性也就是这样分箱的分法,相比上一篇中的那种直接按8162432…这种确定值的分箱方法相对较为复杂,这里是将一个区间内的值分到一个箱子内,正因如此,对于箱内chunk块的管理也就不能再简单的使用双向链表而是使用树(实际上在具体实现上为Trie树,不过和课本上的那种字典Trie树不一样,Doug Lea给出的注释称之为“bitwise digital trees (aka tries)”,要怎么去把它讲清楚还真不简单啊,试着按照从抽象概念到实现细节的方式来说明吧,另外姑且称这种树为dltree树)结构,当然这种树不是随意的,它具有它自身的最简单规则:①任何节点的左子树上所有节点值均小于它的右子树上所有节点值。②任何节点值和它的左(右)子树上所有节点值不存在确定排序关系。这是直白的描述,如果用更严谨的表述则为如下:

dltree树或者是一颗空树;或者是具有下列性质的二叉树:

1)若左子树和右子树都不空,则左子树上所有结点的值均小于右子树上所有结点的值;

2)左、右子树也分别为dltree树;

 

       每一个箱子里的chunk块都被以dltree树结构组织起来,分了32个箱号,因此dlmalloc具有32dltree树,记录该32dltree树根节点的指针变量也定义在结构体malloc_state,如下:

tbinptr    treebins[NTREEBINS];

#define NTREEBINS (32U)

typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */

其中NTREEBINS为常量宏,类型tbinptrmalloc_tree_chunk结构体指针,数组的32个指针元素指向32个分箱内各个dltree树的根节点,因此通过结构体malloc_state类型变量很方便的找到各种chunk块大小范围的树结构。

 

        

 

         下面讨论具体一棵dltree树的组织情况(就以0号箱管理的树为例),根据dltree树中左子树小于右子树的性质,字节[256, 384)范围被按如下规则划分给0号箱管理的dltree树组织:

         根的左子树T1管理[256, 320),右子树T2管理[320, 384),即各管理64字节范围。

       T1的左子树T3管理[256, 288),树T1的右子树T4管理[288, 320),即各管理32字节范围。树T2类似。

       T3的左子树T7管理[256, 272),树T3的右子树T8管理[272, 288),即各管理16字节范围。其它树类似。

       ……

      

 

       通过这种分法,任一号箱的字节范围被对应在一颗树上,在查找某一大小的空闲chunk时则按照这种规律来进行“快速”搜索,比如应用程序malloc( 278 ),则由于278[256, 320)范围内,因此先进入树T1,接着由于278[256, 288)范围内,因此由进入T3,接着进入T8,……。

       之所以说这种搜索是“快速”的,因为这里的范围划为很巧妙,我们来看一下各字节范围用二进制表示的情况:

       根节点T的左子树T1 [256, 320)为:

       [1 0000 0000  1 00xx xxxx]

       而根节点T的右子树T2 [320, 384)为:

       [1 01xx xxxx  1 01xx xxxx]

       其中的x表示为1或者0,可以看到T1T2的管理范围很好区分,即通过判断第6bit位是否为1即可。为1表示在右子树T2范围内,为0表示在左子树T1范围内。

 

       再来看看树T1的左子树T3和右子树T4情况:

       T3管理[256, 288)为:

       [1 0000 0000  1 000x xxxx]

       T4管理[288, 320)为:

       [1 0010 0000  1 001x xxxx]

       可以看到T3T4的管理范围也很好区分,即通过判断第5bit位是否为1即可。为1表示在右子树T4范围内,为0表示在左子树T3范围内。

 

       其它的类似……。因此,我们在查找某字节在哪个范围内的树上只需要顺序的比较各bit位就可以了,对比Trie树,我们可以认为dltree是关键码只有01Trie

 

       还有其他细节,比如当应用程序申请某一字节的内存空间,而该字节所属范围tree不存在时则只有在更接近该范围的tree内申请节点,这些都是具体实现,后面会具体讲到吧。

 

转载请保留本博客地址连接[http://lenky0401.cublog.cn],谢谢。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
dlmalloc是目前一个十分流行的内存分配器,其由Doug Lea(主页为http://gee.cs.oswego.edu/)从1987年开始编写,到目前为止,最新版本为2.8.3(可以从ftp://g.oswego.edu/pub/misc/malloc.c获取),由于其高效率等特点被广泛的使用(比如一些linux系统等用的就是dlmalloc或其变形,比如ptmalloc,主页为http://www.malloc.de/en/index.html)和研究(各位可以搜索关键字“GCspy”)。 dlmalloc的实现只有一个源文件(还有一个头文件),大概5000行,其内注释占了大量篇幅,由于有这么多注释存在的情况下,表面上看上去很容易懂,的确如此,在不追求细节的情况,对其大致思想的确很容易了解(没错,就只是了解而已),但是dlmalloc作为一个高品质的佳作,实现上使用了非常多的技巧,在实现细节上不花费一定的精力是没有办法深入理解其为什么这么做,这么做的好处在哪,只有当真正读懂后回味起来才发现它是如此美妙。 lenky0401个人博客将陆续推出对dlmalloc解析(针对Doug Lea Malloc的最新版Version 2.8.3,未做说明的情况下以32位平台,8字节对齐作为假定平台环境设置考虑),由于个人水平有限,因此也不能完全保证对dlmalloc的所有理解都准备无误, 但是所有内容均出自个人的理解而并非存心妄自揣测来愚人耳目,所以如果读者发现其中有什么错误,请勿见怪,如果可以则请来信告之,并欢迎来信讨论([email protected])。 这一系列文章是lenky0401在看完dlmalloc的大部分代码后的再总结,不能保证对dlmalloc的整体完全把握,贴出这些只是希望可以提前收到对此有研究的网友的指点,以便在最后对这一系列文章整理而形成的PDF文档中错误能少一些。至于对于现在贴出来的内容中包含的错误给大家造成的不便提前说声抱歉。:) 描述的内容不会包含dlmalloc全部代码,但会将这其中涉及到的一些技巧尽量讲出,我相信对dlmalloc源代码不感兴趣的朋友也可以学到这些独立的技巧而使用在自己的编程实践中。:) 最后,转载请保留本博客地址连接[http://lenky0401.cublog.cn],谢谢。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值