这是我参与「第五届青训营 」笔记创作活动的第5天
内存管理分配
Go语言内存分配全局视野
span与元素
当对象需要分配内存时,不是直接分配span而是分配span中的元素
每个具体的对象在分配时需要对齐到指定的大小,例如17字节的对象会被分配到最接近它的元素级别32字节
三级对象管理
-
mcache:每个逻辑处理器P都存储了一个本地span缓存。协程需要内存直接从mcache中获取。mcache包含所有大小规格的mspan,但是每种规格大小只包含一个。除了class0外,mcache的span都来自mcentral
-
mcentral:mcentral被所有逻辑处理器共享。mcentral收集所有给定规格大小的span。每个mcentral包含两个mspan的链表:empty mspanList表示没有空闲对象的span或span已经被mcache缓存的链表,nonemptymspanList表示有空闲对象的span链表
-
mheap:管理mcentral,大对象也会直接通过mheap进行分配
四级内存块管理
对象分配
微小对象
小于16字节的对象。
微小对象会被放入class为2的span中。首先对微小对象按照2、4、8的规律进行字节对齐。
分配过程:
- 如果分配的元素中有空余空间,则增加offset,为下一次做准备(尝试利用分配过的前一个元素的空间,达到节约内存的目的)
- 如果分配的元素空间不够,将尝试从mcache中查找span中下一个可用的元素
mcache缓存位图
mspan中拥有allocCache字段,作为一个位图,用于标记span中元素是否被分配
mcentral遍历span
当前span中没有可以使用的元素,这时需要从mcentral加锁查找。此时会遍历两个链表,这里为什么要遍历没有空闲元素的链表呢?应为可能有些span虽然被垃圾回收器标记为空闲,但是还没有来得及清理
mheap缓存查找
如果在mcentral中找不到可用的span,就需要在mheap中查找
type pageCache struct {
base uintptr
cache uint64
scav uint64
}
每个逻辑处理器都维护了一份pageCache
mheap基数树查找
如果要分配的page过大或者在逻辑处理器的cache中没有找到可用的page
操作系统内存申请
每一次向操作系统中申请的内存大小必须为heapArena的倍数
小对象分配
小对象是指小于32KB的对象
mcache -> mcentral -> mheap -> mheap基数树 -> 操作系统分配
大对象分配
是指大于32KB的对象
直接通过mheap进行分配
总结
这次课不仅讲了内存分配也讲了gc,gc放到下次再写,以上是我在学习过程中结合书本所学