分配一个对象,mutator -> Allocator -> heap分类,从横向来看,可分为线性与链表形式;其中链表又可以分为:首次适应,循环首次适应,最优适应和预先隔离适应。 从纵向来看,可以分为单级与多级。
而golang混合纵向的多级,而各级横向结构有线性形式,也有链表的形式。分配某一对象,按照其大小涉及到的层级不同,可分为微小对象,小对象,大对象三类。
当需要分配这三类对象时,从下面的对应的结构中开始分配
tiny --> 微小对象
mcache ---> 小对象
mcentralList
heapArenasList ---> 大对象
sequential allocation 的实现方式非常简单,只需要把维护的空间直接分配出去就好,每次分配以后挪动指针,指向剩余空闲的位置的首地址,runtime off-heap object allocator一节中介绍的persistent allocator采用的就是sequential allocation这个方式。sequential allocation这种分配方式的缺点是不能直接回收,得配合特定的垃圾回收算法,比如semispace copying collection,这种垃圾回收算法把堆划分成两份,当一份分配完以后,把仍然有用的对象拷贝到另外半个堆中,这样没有用的对象的空间就被回收了,分配空间继续在另外半个堆进行,当满了以后再拷贝有用的对象回到原来的半个堆中。
free list allocation 这种分配方式相对sequential allocation这种方式没能更好的利用上缓存的空间局部性原理,并且分配的时候速度慢,虽然有first fit 、next fit、best fit三种寻找空闲块的策略 ,但是多少还是会造成外部碎片。但是free list allocation 可以支持立马把释放的空间放到list中用于后续的分配。
segregated-fix allocation 是属于fee list allocation的一种细分
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
//...
if size <= maxSmallSize {
if noscan && size < maxTinySize {
// 微对象分配
} else {
// 小对象分配
}
} else {
// 大对象分配 largeAlloc
}
//...
}