分级分配机制
借鉴了线程缓存分配(Thread-Caching Malloc,TCMalloc)的设计实现高速的内存分配
核心理念:使用多级缓存将对象根据大小分类,并按照类别实施不同的分配策略。
内存管理组件
内存管理的基本单元mspan
mspan之间形成双向链表结构
每个mspan 都管理 npages 个大小为 8KB 的页
以页为单位向堆申请内存,以对象为单位查找分配空间
67种跨度类spanClass
决定了mspan存储的对象大小和个数
每一个跨度类都会存储特定大小的对象并且包含特定数量的页数以及对象
存储类别ID 为 0 的特殊跨度类,它能够管理大于 32KB 的特殊对象
含有noscan 标记位,表示存储对象是否包含指针,方便后期垃圾回收
线程缓存mcache
同处理器P绑定,主要用来缓存用户程序申请的微小对象。无锁访问内存管理单元
每一个线程缓存都持有 67 * 2 个 mspan
初始化:初始化时是不包含 mspan 的
替换:只有当用户程序申请内存时才会从上一级组件获取新的 mspan 满足内存分配的需求。
内含三个字段组成了微对象分配器
只会用于分配非指针类型的内存
默认为 16 字节以下的对象申请和管理内存
中心缓存mcentral
访问中心缓存中的内存管理单元需要使用互斥锁
内含2个mSpanList
有空闲对象的未满 mspan 结构
没有空闲对象的满的 mspan
每个mcentral都是一种mspan的全局后备资源
mcache从mcentral获取mspan过程
页堆mheap
持有的 134 个mcentral
一个全局的结构体,统一管理堆上初始化的所有对象
内部采用二维矩阵 runtime.heapArena管理所有内存空间,内存可以是不连续的:
Linux 的 x86-64架构上,单个 Go 语言程序的内存上限也就是 256TB
从堆中申请内存的途径
处理器的页缓存 runtime.pageCache
全局的页分配器 runtime.pageAlloc
之间联系
中心缓存属于页堆,它会从操作系统中申请内存,会维护全局的内存基本单元,各个线程会通过中心缓存获取新的内存单元
内存分配策略
微对象 (0, 16B)
先使用微型分配器,再依次尝试线程缓存、中心缓存和堆分配内存;
小对象 [16B, 32KB]
依次尝试使用线程缓存、中心缓存和堆分配内存;
大对象 (32KB, +∞)
直接在堆上分配内存;
其他
内存管理模块中一共包含 67 种跨度类
Linux 的 x86-64架构上,单个 Go 语言程序的内存上限也就是 256TB
采用类似 TCMalloc 的分配策略将对象根据大小分类,并设计多层级的组件提高内存分配器的性能。