- page:页是操作系统中用来描述内存大小的一个单位名称,一个页的含义是大小为4K(1024*4=4096字节)
- span:多个先连续的page组成的一片区域
接下来看看几个重要的数据结构。
// 存储单元
type mspan struct {
_ sys.NotInHeap
// 这里标识前后节点的指针
next *mspan // next span in list, or nil if none
prev *mspan // previous span in list, or nil if none
// span 起始的地址
startAddr uintptr // address of first byte of span aka s.base()
// 占用的页数
npages uintptr // number of pages in span
// 标识此前前的位置已经被占用
freeindex uintptr
// TODO: Look up nelems from sizeclass and remove this field if it
// helps performance.
// 最多可以存放多少个object
nelems uintptr // number of object in the span.
// bitmap 每个bit对应的object快,标识该块是否被占用
allocCache uint64
// span的等级
spanclass spanClass // size class and noscan (uint8)
...
}
// 线程缓存
type mcache struct {
_ sys.NotInHeap
nextSample uintptr // trigger heap sample after allocating this many bytes
scanAlloc uintptr // bytes of scannable heap allocated
// 为对象分配内存相关
tiny uintptr
tinyoffset uintptr
tinyAllocs uintptr
// The rest is not accessed on every malloc.
// numSpanClasses = 136
// numSpanClasses = 136 = 67(size classes)× 2(scan/noscan) + 保留 class
//
alloc [numSpanClasses]*mspan // spans to allocate from, indexed by spanClass
stackcache [_NumStackOrders]stackfreelist
// flushGen indicates the sweepgen during which this mcache
// was last flushed. If flushGen != mheap_.sweepgen, the spans
// in this mcache are stale and need to the flushed so they
// can be swept. This is done in acquirep.
flushGen atomic.Uint32
...
}
// 中心缓存
type mcentral struct {
_ sys.NotInHeap
// 对应一种spanClass
spanclass spanClass
// 可以再继续分配的mspan的集合
partial [2]spanSet // list of spans with a free object
// 暂时满了的集合 等带GC回收之后回归可用
full [2]spanSet // list of spans with no free objects
}
// 堆缓存
type mheap struct {
lock mutex // 全局锁,保护大部分字段
pages pageAlloc // 页分配器,负责分配大块的页
sweepgen uint32 // 垃圾回收相关的代数标记
sweepdone uint32 // 所有 span 是否都已清扫
spans []*mspan // spans 数组,用于记录每一页属于哪个 span
arenas []*heapArena // 指向 arena 的切片,每个 arena 管理 64MB 的空间
allspans []*mspan // 所有的 span(用于 sweep)
central [numSpanClasses]mcentral // 所有 spanClass 对应的 mcentral
busy uint64 // 用于调试 & 统计
...
}