这是我参与「第五届青训营 」伴学笔记创作活动的第 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 都对应一个链表。
Central Cache:线程共享,包含一个空闲链表数组,结构与 Thread Cache 的相同。当 Thread Cache 内存不足时,可以从 Central Cache 获取。
Page Heap:线程共享,包含一个空闲链表数组,每个链表中的元素为 Span,同一个链表中 Span 大小相同。
小对象分配
- 根据要分配对象的大小,映射到相应的 Size Class;
- 如果 Thread Cache 对应的空闲链表不为空,则返回第一个空闲对象;
- 如果 Thread Cache 不够用,则从 Central Cache 获取;
- 如果 Central Cache 不够用,则从 Page Heap 获取;
- 如果 Page Heap 不够用,则向操作系统申请内存。
大对象分配
大对象指的是大于 32KB 的对象,它们的分配是在 Page Heap 中完成的。