TCMalloc | 青训营笔记

116 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天,记录一下对 go 语言内存管理中 TCMalloc 算法的学习。

简介

TCMalloc 的全称是 Thread-Caching Malloc,是 Google 开发的内存管理算法库,也是 go 语言内存管理的核心算法。它有减少内存碎片、适用于多核、更好的并行性支持等特性。

简单来说,TCMalloc 内存分配采用分级策略。每个线程都有自己的私有内存池,线程独占,用于小内存的分配,无需加锁,大大减少了内存分配时的锁竞争。全局内存池线程共享,用于大容量内存的分配以及线程私有内存池空间不足时的分配,需要加锁。内存池的数据结构为数组 + 链表,数组的每个元素是一个链表,链表中的每个元素大小相同。

相关概念

Page:TCMalloc 管理内存的单位,默认 8KB。

Span:由一组连续的 Page 组成。

Size Class:对于 256KB 以内的小对象,按大小划分的类别。每个 Size Class 都对应一个大小,如8字节、16字节、32字节。

Thread Cache:线程独占,包含一个空闲链表数组,同一个链表中拥有相同大小的空闲对象,即每个 Size Class 都对应一个链表。

threadheap.gif

Central Cache:线程共享,包含一个空闲链表数组,结构与 Thread Cache 的相同。当 Thread Cache 内存不足时,可以从 Central Cache 获取。

Page Heap:线程共享,包含一个空闲链表数组,每个链表中的元素为 Span,同一个链表中 Span 大小相同。

pageheap.gif

小对象分配
  1. 根据要分配对象的大小,映射到相应的 Size Class;
  2. 如果 Thread Cache 对应的空闲链表不为空,则返回第一个空闲对象;
  3. 如果 Thread Cache 不够用,则从 Central Cache 获取;
  4. 如果 Central Cache 不够用,则从 Page Heap 获取;
  5. 如果 Page Heap 不够用,则向操作系统申请内存。
大对象分配

大对象指的是大于 32KB 的对象,它们的分配是在 Page Heap 中完成的。

参考

gperftools.github.io/gperftools/…

knifefly.cn/2019/10/03/…

www.cnblogs.com/jiujuan/p/1…

wallenwang.com/2018/11/tcm…