Go 内存分配机制原理
Go 的内存分配机制设计非常精细,结合了多级缓存、对象池和垃圾回收等机制,以实现高并发下的高性能分配。
1. 整体内存结构
Go 程序启动时,运行时会向操作系统申请一大块连续内存区域(heap arena),这个区域主要被划分为三个部分:
- arena:主要用于实际存放用户对象;arena即为所谓的堆区,应用中需要的内存从这里分配。512G;arena区域划分成一个个的page,每个page为8KB,一共有512GB/8KB个页
- bitmap:主要用于 GC使用;16G
- spans:用来管理 arena 中的一段段页(page)资源。512M;spans区域存放span的指针,每个指针对应一个page,所以span区域的大小为(512GB/8KB)*指针大小8byte = 512M
2. 多级分配体系:MCache、MCentral、MHeap
Go 的内存分配基于分级缓存结构,具体如下:
-
MCache(线程本地缓存)
每个 P(Processor)对应一个 MCache,是最靠近线程的分配器,分配最快,不需要加锁。 -
MCentral(中心缓存)
所有线程共享,负责按“大小类别(size class)”管理多个 span。
当 MCache 缺资源时,从 MCentral 拉取新的 span。 -
MHeap(堆)
管理所有 span 和 page,从操作系统申请内存,提供大对象支持。
MCentral 资源不足时,就会从 MHeap 拉取。
这是 “三级内存分配架构”,分别优化了不同粒度的分配效率与并发冲突。
3. 内存分配流程简述!!!
当程序需要分配内存时:
- 小对象(<32KB):根据 size class 直接从 MCache 中拿对象;
- 如果 MCache 没有,就从 MCentral 拉取 span;
- 如果 MCentral 没有,就从 MHeap 获取 page,构造 span;
- 大对象(≥32KB):直接从 MHeap 分配整页,跳过缓存层。
4. GC 与内存协同
Go 的垃圾回收器采用 并发三色标记-清除算法,与分配体系紧密协作:
- GC 通过 bitmap 和 span 表追踪对象;
- 在 GC 过程中会发生短暂的 STW(Stop-The-World);
- 回收后的 span 会归还给 MCentral,再被重用。
https://github.com/0voice