GO语言内存管理结构
文章目录
- 1、内存分区
- 1.1、栈(Stack)
- 1.2、堆(Heap)
- 2、堆内存管理结构
- 2.1、内存分配器(MCache → MArena → MSpan → MHeap)
- 2.2、大小分类(Size Class)
- 2.3、分配流程
- 3、垃圾回收(Go语言堆空间自动回收)
- 4、性能优化点
1、内存分区
Go 的内存主要分为两部分:栈(Stack)、堆(Heap)。
1.1、栈(Stack)
由编译器自动分配/释放,存储函数调用时的局部变量、参数、返回值等。
每个 Goroutine 有独立的栈(初始大小 2KB,可动态扩容/缩容)。
分配速度快(无需 GC 参与),但空间有限。
1.2、堆(Heap)
动态分配的内存(如 new、make 或逃逸分析的变量)。
由垃圾回收器(GC)自动管理,开发者无需手动释放。
分配速度较慢,但空间更大。
2、堆内存管理结构
Go 的堆内存通过多级缓存和分区策略高效管理:
2.1、内存分配器(MCache → MArena → MSpan → MHeap)
MCache(Per-P 缓存):
1、每个逻辑处理器(P)绑定的本地缓存,存储小对象(≤32KB)的分配。
2、无锁分配,提高并发性能。
MSpan(内存块管理单元):
1、一组连续的内存页(8KB 的倍数),按大小分类(如 8B、16B、…、32KB)。
2、通过 mspan 结构体管理,记录分配状态。
MArena(堆区抽象):
1、将堆划分为多个 Arena(64位系统默认每个 64MB),用于大对象分配。
MHeap(全局堆):
1、管理所有 MSpan,负责向操作系统申请/释放内存(通过 mmap 或 brk)。2、包含空闲列表(free 和 busy 链表)。
2.2、大小分类(Size Class)
将对象按大小分为约 70 个等级(如 8B、16B、24B…)。
每个等级对应固定的 MSpan,减少内存碎片。
2.3、分配流程
小对象(≤32KB):
优先从当前 P 的 MCache 分配 → 不足时从 MHeap 获取新的 MSpan。
大对象(>32KB):
直接从 MHeap 分配,绕过 MCache。
3、垃圾回收(Go语言堆空间自动回收)
Go 使用 三色标记-清除算法(并发标记 + STW 清扫):
1、标记阶段:遍历可达对象(从根对象 Goroutine 栈、全局变量等出发)。
2、清除阶段:回收不可达对象的内存。
3、写屏障(Write Barrier):保证并发标记时数据一致性。
4、分代策略:Go 1.12+ 引入局部代际优化(但非传统分代 GC)。
4、性能优化点
1、减少堆分配:避免指针逃逸、复用对象(如 sync.Pool)。
2、控制 GC 频率:调节 GOGC 环境变量(默认 100%)。
3、监控工具:
runtime.ReadMemStats 获取内存统计。
pprof 分析内存泄漏。