tcmalloc内存管理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010318270/article/details/89349987

一、前言

1、如何分配定长记录
例如,我们有一个page的内存,大小为4kb,现在要以n个字节为单位进行分配。为了简化问题,就以16字节为单位进行分配。
将4kb的内存划分为16字节的单元,每个单元的前8个字节作为节点指针,指向下一个单元。初始化的时候把所有指针指向下一个单元。
分配时,从链表头分配一个对象出去,释放时,插入到链表。
由于链表指针直接分配在待分配内存中,因此不需要额外的内存开销,而且分配速度也是相当快。

2、如何分配变长记录
对于分配变长记录,把问题化归成对多种定长记录的分配问题。
8、16、32、48、...、256kb

3、大的对象如何分配
如果分配的对象大于一个page,就需要多个page来分配了。多个连续page组成span,大对象直接分配span,小对象在span中分配object。在span中记录起始page的编号,以及page数量。

4、span如何分配
对于span的管理,采用和上边类似的方法。1、2、3、4、...、128page
用多种定长page来实现变长page的分配,初始时只有128page的span,如果分配1个page的span,就把这个span分裂成两个1+127,把127再记录下来。
对于span的回收,需要考虑span的合并问题,否则在分配回收多次之后,就只剩下很小的span了,也就是外来外碎片问题。
因此,释放span时,需要将前后的空闲span进行合并,前提是它们的page是连续的。

5、如何知道前后的span在哪里
由于span中记录了起始page,也就是知道了从span到page的映射,那么我们只要知道从page到span的映射,就可以知道前后的span是什么了。
最简单的方式是用一个数组记录每个page所属的span,而数组索引就是page id。这种方式虽然简洁明了,但是在span比较少的时候会有很大的空间浪费。
为此,可以使用RadixTree(基数树)这种数据结构,用较少的空间开销和不错的速度来完成这件事。

二、ThreadCache、CentralCache、PageHeap

1、PageHeap
至此,我们已经实现了PageHeap,对所有page进行管理。
通过PageMap实现page到span的映射;通过伙伴系统,实现span的分裂与合并。

2、CentralCache全局对象分配
既然有了基于page的对象分配,和page本身的管理,把它们串起来就可以得到一个简单的内存分配器CentralCache。
每种规则的对象,都有一个CentralCache。向PageHeap申请span,为用户分配对象。
每种规格的对象,都从不同的span进行分配,每种规则的对象都有一个独立的内存分配单元:CentralCache。
在一个CentralCache内存,用链表把所有span组织起来,每次需要分配时就找一个span从中分配一个object。
当没有空闲的span时,就从PageHeap申请span。

这里有一个严重的问题,在多线程的场景下,所有线程都从CentralCache分配的话,竞争可能相对激烈。

扫描二维码关注公众号,回复: 5919631 查看本文章

3、ThreadCache
每个线程都有一个线程局部的ThreadCache,按照不同的规格,维护了对象的链表;如果ThreadCache的对象不够了,就从CentralCache进行批量分配;如果CentralCache依然没有,就从PageHeap申请span;如果PageHeap没有合适的page,就只能从操作系统申请了。

在释放内存时,ThreadCache依然遵循批量释放的策略,对象积累到一定程度就释放给CentralCache;CentralCache发现了一个span的内存完全释放了,就可以把这个span归还给PageHeap;PageHeap发现了一批连续的page都释放了,就可以归还给操作系统。

三、总结

ThreadCache:每个线程一份,每个线程的内存需求都在自己的ThreadCache里面完成,线程之间不需要竞争。
CentralCache和PageHeap是全局的。

内存分配粒度:有两种粒度的内存object和span,span是连续page的内存,而object则是由span切出来的小块。
object的尺寸被预设了一些规格(class),比如16字节、32字节等,同一个span切出来的object都是相同的规格。
object不大于256k,超大的内存将直接分配span来使用。

ThreadCache和CentralCache都是管理object,而PageHeap管理的是span。

参考文献:
http://www.cs.cmu.edu/afs/cs/academic/class/15213-s11/www/lectures/20-allocation-advanced.pdf
https://zhuanlan.zhihu.com/p/29216091
https://yq.aliyun.com/articles/6045

猜你喜欢

转载自blog.csdn.net/u010318270/article/details/89349987