GO语言内存管理结构

发布于:2025-05-12 ⋅ 阅读:(20) ⋅ 点赞:(0)

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 分析内存泄漏。