- tcmalloc(即Thread-Cache Malloc)是一个通用的内存分配器,使用tcmalloc只需要在编译的链接阶段加入-ltcmalloc,而不是使用glibc(ptmalloc2),不需要有任何的代码改动。也就是说用户在使用malloc/free、new/delete时会使用tcmalloc进行内存分配。
- 为什么要使用tcmalloc
主要是因为性能,tcmalloc能提供更快的申请/释放速度,而且内存利用率更高,产生更少的内存碎片
- 原理:先上图
-
- 基本概念:
Free List:数组链表,链表中保存了内存块
objects:内存块
Page:页内存,内存分隔成大小固定,地址对齐的块
Span:tcmalloc管理内存的单位,一个Span可以包含一个或多个Page
Radix Tree:基数树,是一种广泛用于内存管理的数据结构,这里用来管理Span
?
-
- 组织结构:
tcmalloc以256k为界将内存分成大块内存和小块内存,使用不同的策略分别对这两种内存进行管理。从图中可以看到,tcmalloc由若干(线程数)个Thread Cache,一个Central Heap和一个Page Heap组成。这三种结构中都包含一个数组,而数组的元素是一个链表。数组链表是tcmalloc管理内存的主要数据结构之一。三者所不同的是,Thread Cache的链表(FreeList)内容是object,是被切分的小的内存块;Central Heap(FreeList)和Page Heap(SpanList)的链表内容是Span,但Central Heap的Span中又有切分的object。
-
- 小内存的分配策略
小内存的管理由两部分构成:Thread Cache和Central Heap。其中Thread Cache是线程本地Cache,每个线程一个;Central Heap则由所有线程共享。
当一个线程申请内存时,首先响应的是Thread Cache,如 大专栏 tcmalloc原理分析果其中有足够大的内存满足要求,可直接返回。只有当内存不够时,需要向Central Heap申请,此时使用了一个细粒度的自旋锁来保证线程安全。如果Central Heap没有足够内存该怎么办呢,后面会讲到具体策略。
?
由上可知,小内存的分配在大部分情况下都是预分配好的,可以拿来即用,只有在本地Cache不足的情况才需要加锁,因此效率很高。
-
- 大内存的分配策略
大内存通过Page Heap来管理内存,策略与小内存相似,也是预分配好一个数组链表,不同的是Page Heap只有一个,而且实际上Central Heap的Span也是从Page Heap上分配出去的。
Page Heap的数组共256项,每项中的Span依次包含1-255个Page,最后一项的Span包含大于等于256个Page。当数组中的第k项已经没有Span时,可以从第k+1项拿一个Span,将这个Span拆成一个包含k个Page的Span提供给申请者,一个包含1项的Span放到数组的第1项中。如果第k+1项同样没有Span则继续项第k+2项申请,依次类推。
-
- 内存回收
???????? 当释放一个内存对象时,需要先根据地址计算出页号,再在Radix Tree中找到页号对应的Span,根据Span确定是小内存还是大内存对象。
???????? 如果是小内存,需要把它插入内存本地的FreeList中,如果线程本地内存cache超过阈值(默认2MB),会使用策略将部分未使用的内存块移动到Central Heap中,此时放到了central cache中的tc_slots_中,而不是直接放入Span中,只有当tc_slots_满了,才会归还到Span中,这样的好处是在Thread Cache和Central Heap中又加入了一层缓存使效率更高。
???????? 如果是大内存,还要获取这个Span页的前一页和后一页是否空闲,如果都不空闲,则直接将这个Span放入SpanList合适的位置,如果这个Span的前一页或后一页存在空闲,还需要将这个Span与前面或后面的Span合并后再把新的Span放入合适的SpanList中。例如,Span1包含[m, n-1]页,Span2包含[n, k-1]页,Span3包含[k, s]页,此时回收了Span2,如果检查发现第n-1页空闲,第k页非空闲,此时需要将Span1和Span2合并成一个包含[m, k-1]页的新Span,而如果第n-1页和第k页都空闲的话,则合并后的新Span应包含[m,s]页。
4.?? ?后记
???????? 使用tcmalloc后,不必再费尽心思去在代码中设计内存池,而且使用时不需要包含任何头文件,只需要在链接环节使用-ltcmalloc代替glibc即可,这是作为一款通用内存管理器的便捷之处。同时在效率上可以得到数倍的提升。
???????? 其实tcmalloc中还有很多细节值得研究,我们应该学习其中优秀的编程思想,同时也希望通过以上分析对理解tcmalloc有所帮助。
?
?
原文地址:https://www.cnblogs.com/wangziqiang123/p/11696929.html