Go 内存分配器解析
·
内存分配器
实现了高并发环境下高速、低延迟内存分配,同时降低锁竞争和内存碎片
1 设计原理
分级分配
将内存划分为多级缓存,根据对象大小进行分类处理
- 对象分级:微对象(<16B)、小对象(16B~32KB)、大对象(>32KB)三类
- 缓存分级:内存管理机构分为线程缓存(mcache)、中心缓存(mcentral)、页堆(mheap)。
- 分配策略:分配时,优先从更靠近线程、无锁的本地缓存(mcache,每个P都有)分配,没有时,逐级向上申请。
虚拟内存布局
Go 程序启动时,会向系统申请一大段连续的虚拟内存地址空间(mheap),整个堆划分为一个个 arena 区域,每个 64MB。
地址空间
内存分配器以 page 为单位与 OS 交互,大小为OS页的整数倍(如8KB)以便与操作系统虚拟内存对齐。Go 运行时通过 mheap 结构管理着所有这些虚拟内存页的分配和释放。
- 栈区:每个goroutine独立栈,初始2KB,无需GC
- 堆区:运行时管理,包含所有动态分配对象,通过GC回收
- 其他区域:代码段、数据段
2 内存管理组件
Go 内存分配器的核心是 mcache → mcentral → mheap 三级缓存结构,逐级降低锁粒度。
2.1 内存管理单元:mspan
内存管理的基本单元,代表一段连续的物理页,由 startAddr(起始地址)和 npages(页数)标识。
核心功能
spanclass按 size class 划分为67种,每个mspan仅管理同一种 size class 的对象。- 通过
allocBits位图,标记哪些内存块已被分配,快速定位空闲对象槽,实现快速分配 gcmarkBits用于标记内存的回收情况
mspan 不存储用户数据,仅维护元数据(地址、页数、位图)
2.2 线程缓存:mcache
- 每个 P 本地私有,无锁访问
- 持有 68*2 个 mspan,只有当用户申请内存时
- 工作流程:
- 分配小对象,直接从 mcache 的对应链表中取出空闲槽,速度快
- 若当前 size class 的 mspan 耗尽,向 mcentral 申请补充(加锁)
- 释放对象时,优先归还到 mcache,以便快速复用
- 核心价值:大部分内存分配在本地无锁完成,降低竞争
2.3 中心缓存:mcentral
- 全局共享的缓存,按照size class 组织,每个size class 对应一把锁(细粒度)
- 68 个 mcentral 示例,每个实例管理一个 size class 的 mspan 链表,分别存储包含空闲对象和不包含空闲对象的内存管理单元。
- 工作流程
- 当 mcache 需要补充 mspan 时,向对应 size class 的 mcentral 申请
- mcentral 没有时,向 mheap 申请新内存页(全局锁)
- 关键设计:锁细化到 size class,避免所有分配竞争同一把锁
2.4 页堆:mheap
- 全局唯一的堆内存管理者,与 OS 交互
- 核心功能
- 存储所有 spanclass 对应的 mcentral
- 向 mcentral 提供新的内存页
- 周期性将空闲内存归还 OS
- 大对象分配或缓存耗尽时才访问 mheap,加全局锁
3 内存分配
runtime.mallocgc
微对象 (Micro Object, < 16B)
对于极小且不包含指针的对象,Go 使用 tiny 分配器进行优化。
每个 mcache 都有一个 16 字节的 tiny 内存块。新来的微对象会尝试塞进这个 tiny 块的空闲部分。如果空间不足,才会从 mcache 中申请一个新的 16 字节 mspan 来替换。这极大地减少了内存碎片和分配次数。
小对象 (Small Object, 16B - 32KB)
小对象是 Go 程序中最常见的分配类型。其分配路径如下:
- 尝试
mcache: 根据对象大小找到对应的spanClass,直接从 P 绑定的mcache的mspan中分配,无锁。 - 向
mcentral请求: 若mcache中对应的mspan已无空闲块,则向全局的mcentral加锁申请一个新的mspan。 - 向
mheap请求: 若mcentral也无可用的mspan,则会向mheap申请一组新的内存页来生成mspan。 - 向 OS 请求: 若
mheap内存不足,最终会向操作系统申请新的内存。
大对象 (Large Object, > 32KB)
大对象的分配路径最直接:
- 直接向
mheap分配: 不会经过mcache和mcentral。 - 按页计算:
mheap根据对象大小计算出需要多少页,直接分配一个或多个连续的页,构成一个mspan返回。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)