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

来源:互联网 发布:java运维面试题 编辑:程序博客网 时间:2024/05/17 16:45

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

该层的分配需要锁。CentralCacheThreadCache之间的空闲链表是一一对应的,以子链表为单位(obj个数很可能为num_objects_to_movecl),见do_mallocdo_free流程图)进行互相交换。

CentralCache的内存从PageHeap里获得。从PageHeap获得的内存叫Span。一个Span在使用时只能用于同一大小的空闲链表,一但CentralCachePageHeap中获取新的Span,这个Span就是一个串好的相同大小内存的空闲链表。

Centralcache中有几个重要数据结构:

1.     TCEntry  tc_slots_[kMaxNumTransferEntries];

tc_slots_每个节点存放的是一组obj链表,这一组obj的个数为num_objects_to_moveTCEntry结构体有两指针,分别指向这个链表的头和尾。

tc_slots_存放的是threadCacheCentralCache归还的obj链表,并且只有当个数满足num_objects_to_move时,才会放入tc_slots_。否则归还的obj根据其所处的span,进行归还,若对应的spanempty,那么由于此时被归还内存了,所以其有空闲obj了,便把该spanempty队列清除,把其加入nonempty队列。

2.      span empty

FetchFromSpans函数把一个objnonempty队列中的一个span中切出,准备给threadCache。当切完这个obj后,如果该span已经没有内存空间了,那么便把该spannonempty队列移除,并加入empty队列。

3.     span nonempty

CentralCache从中央页堆申请页面,中央页堆以span的形式返回。在CentralCache中会把该span切成大小为class_to_sizeobj,并把所有的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)第四层,系统页面分配,

这就是调用系统函数了。

0 0
原创粉丝点击