注意: 内存分配器只管理内存块, 不关心内存中对象的状态, 也不会主动的回收内存, 回收是在回收器完成清理操作后, 触发内存分配器的回收操组;
span面向内部管理, object面向对象分配
malloc.go
pageShift = _PageShift
_PageSize = 1 << _PageShift // 8kb
mheap.go
type mspan struct {
next *mspan // 双向链表
prev *mspan
start pageID // 起始序号 = (address >> _pageshift)
npages uintptr // 页数
freelist gclinkptr // 带分配的object 链表
...
}
malloc.go
_MaxSamllSize = 32 << 10 //32kb
优秀的内存分配器必须要在性能和内存利用率之间做到平衡. go的起点很高, 直接采用了tcmalloc架构
malloc.go
// Memory allocator.
//
// This was originally based on tcmalloc, but has diverged quite a bit.
// http://goog-perftools.sourceforge.net/doc/tcmalloc.html
mheap.go
type mheap strcut {
free [_MaxMheapList]mspan // 页数在127以内的闲置span链表数组
freelarge mspan // 页数大于127(>=1MB)的大span链表
// 每个central 对应一种 sizeclass
central [_NumSizeClass]struct{
mcentral mcentral
}
}
mcentral.go
typt mcentral strcut {
sizeclass int32 // 规格
nonempty mspan // 链表, 尚有空闲的object 的span
empty mspan // 链表, 没有空闲的object, 或已被cache取走的span
}
mcache.go
type mcache struct {
alloc [_NumSizeClasses]*mspan // 以sizeclass为索引管理多个用于分配的span
}
# cache.alloc --> span.freelist --> central --> central.nonempty --> heap.free/freelarge
注意: 分配和回收不包括大对象, 他直接从heap分配和回收
cache 是工作线程私有且不被共享, 是实现高性能无锁分配的核心.
central 的作用是在多个cache间提高object的利用率.避免内存浪费.
假设cache1 获取一个span后, 仅仅使用了一部分object, 那么剩余的空间就可能会被浪费, 而回收操作将该span交换给central后, 该span完全可以被cache2 cache3 ... 获取使用, 此时 cache1 不再持有该span, 完全不会造成问题
将span归还给heap, 是为了在不同规格object需求间平衡
某段时间内某种规格的object需求可能激增, 当需求过后, 大量的被切分成该规格的span就会闲置浪费, 将其归还给heap, 就可以被其他需求获取, 重新切分
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。