您的位置:首页 > 其它

TCMalloc的使用与源码剖析之三---------TCMalloc的内存分配的主要层次

2016-10-22 10:32 211 查看

(1)第一层,线程局部分配,ThreadCache

       ThreadCache包含了一个不同对象大小的空闲链表数组,其实现采用操作系统的线程局部存储功能。分配时几乎不需要用锁,除非触发CentralCache的操作。
ThreadCache中的重要数据结构:




pthread_t     tid_;   绑定线程,达到每个线程有个缓冲池的目的
FreeList      list_[kNumClasses]; 
这个数组就是上图中的第一列,如下图
 


数组中的每一个节点就是代表上图中的每一行,如下图



每个class对应多大的内存空间?这个表示每组的大小的变量在哪里?
不存在这样的变量,但是通过映射关系可以达到一个class管一类size的作用,
如下图所示,由cl
得到list_[cl],这也即是一个class。



至于cl,是由class_array_得到的,关于这个内容在第五章:几个重要的数据结构

若申请的内存是13字节,但分配的却是15字节,那么便会有2个字节的内存碎片(内部碎片)。

(2)第二层 ,中心分配,Centralcache

该层的分配需要锁。CentralCache和ThreadCache之间的空闲链表是一一对应的,以子链表为单位(obj个数很可能为num_objects_to_move(cl),见do_malloc与do_free流程图)进行互相交换。
CentralCache的内存从PageHeap里获得。从PageHeap获得的内存叫Span。一个Span在使用时只能用于同一大小的空闲链表,一但CentralCache从PageHeap中获取新的Span,这个Span就是一个串好的相同大小内存的空闲链表。
Centralcache中有几个重要数据结构:
1.     TCEntry  tc_slots_[kMaxNumTransferEntries];
tc_slots_每个节点存放的是一组obj链表,这一组obj的个数为num_objects_to_move,TCEntry结构体有两指针,分别指向这个链表的头和尾。
tc_slots_存放的是threadCache向CentralCache归还的obj链表,并且只有当个数满足num_objects_to_move时,才会放入tc_slots_。否则归还的obj根据其所处的span,进行归还,若对应的span是empty,那么由于此时被归还内存了,所以其有空闲obj了,便把该span从empty队列清除,把其加入nonempty队列。
2.      span empty
FetchFromSpans函数把一个obj从nonempty队列中的一个span中切出,准备给threadCache。当切完这个obj后,如果该span已经没有内存空间了,那么便把该span从nonempty队列移除,并加入empty队列。

3.     span nonempty

CentralCache从中央页堆申请页面,中央页堆以span的形式返回。在CentralCache中会把该span切成大小为class_to_size的obj,并把所有的obj链接起来,链表头为span->objects。再把该链表加入nonempty队列。

Nonempty队列另外一个被加入span的地方在内存从threadCache归还给CentralCache时,具体情况见上面”tc_slots_”这一数据结构的描述。

 

(3)第三层,中央页堆,PageHeap

       PageHeap以一定数量连续页面内存的形式提供内存。这组连续的页面由一个Span对象描述,Span对象和它描述的页面内存是独立的。Span对象保存了页面的id序列,页面id左移一个page就是内存的地址。由于页面和Span内存独立,需要用page
id反向映射查找Span对象就需要单独的映射表。这个表用radix tree实现,兼顾效率和内存。PageHeap还负责合并和拆分相邻的Span。
PageHeap重要数据结构:
SpanList   large_;
SpanList   free_[kMaxPages];
中央页堆是由空闲内存列表组成的数组。对于i< 256而言,数组的第k个元素是一个由每个单元是由k个页面组成的空闲内存链表(这也即是free_)。第256个条目(这即是large_)则是一个包含了长度>=
256个页面的空闲内存链表:



而SpanList为
struct SpanList {
    Span       normal;
    Span       returned;
  };
Returned代表的是已经归还给系统的span
 

(4)第四层,系统页面分配,

这就是调用系统函数了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息