本教材由知了传课辛苦制作而成,仅供学习使用,请勿用于商业用途!如进行转载请务必注明出处!谢谢!

go内存

一、分配内存的两个方法

1.make:返回Type

2.new:返回*Type

一、go内存介绍

内存分配算法TCMalloc(Thread-Caching Malloc),看第2节

二、内存管理流程

1.arena,bitmap,spans

程序启动的时候,会先向操作系统申请一块虚拟内存,然后切成小块后自己进行管理。申请到的内存块被分配了三个区域,在X64上分别是512MB(spans),16GB(bitmap),512GB(arena)大小

arena

堆区,用来动态分配内存,把内存分割成8KB大小的页,一些页组合起来称为mspan。

bitmap

标识arena区域哪些地址保存了对象,并且用4bit标志位表示对象是否包含指针、GC标记信息。
bitmap中一个byte大小的内存对应arena区域中4个指针大小(指针大小为 8B )的内存

spans

存放mspan的指针,也就是一些arena分割的页组合起来的内存管理基本单元,
每个指针对应一页,创建mspan的时候,按页填充对应的spans区域,在回收对象时,
根据地址很容易就能找到它所属的mspan

2.内存管理单元

mspan是Go中内存管理的基本单元,是由一片连续的8KB的页组成的大块内存,mspan是一个包含起始地址、mspan规格、页的数量等内容的双端链表

mspan源代码路径:goroot下的 \src\runtime\mheap.go:335

type mspan struct { //链表前向指针,用于将spans链接起来 next *mspan //链表前向指针,用于将spans链接起来 prev *mspan // 起始地址,也即所管理页的地址 startAddr uintptr // 管理的页数 npages uintptr // 块个数,表示有多少个块可供分配 nelems uintptr //分配位图,每一位代表一个块是否已分配 allocBits *gcBits // 已分配块的个数 allocCount uint16 // class表中的class ID,和Size Classs相关 spanclass spanClass // class表中的对象大小,也即块大小 elemsize uintptr } type span struct { start int end int }

3.内存管理组件

  • mcache

mcache在初始化时没有任何mspan资源,在使用过程中会动态地从mcentral申请

goroot下的 \src\runtime\mcache.go:19

type mcache struct { next_sample uintptr // trigger heap sample after allocating this many bytes local_scan uintptr // bytes of scannable heap allocated tiny uintptr tinyoffset uintptr local_tinyallocs uintptr // number of tiny allocs not counted in other stats alloc [numSpanClasses]*mspan stackcache [_NumStackOrders]stackfreelist // Local allocator stats, flushed during GC. local_largefree uintptr // bytes freed for large objects (>maxsmallsize) local_nlargefree uintptr // number of frees for large objects (>maxsmallsize) local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize) // 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 uint32 }
  • mcentral

为所有mcache提供切分好的mspan资源,每个mcentral对应一种sizeClass的mspan

goroot下的 \src\runtime\mcentral.go:20

type mcentral struct { // 互斥锁 lock mutex // 规格 sizeclass int32 // 尚有空闲object的mspan链表 nonempty mSpanList // 没有空闲object的mspan链表,或者是已被mcache取走的msapn链表 empty mSpanList // 已累计分配的对象个数 nmalloc uint64 }
  • mheap

堆空间。当mcentral没有空闲的mspan时,会向mheap

goroot下的 \src\runtime\mheap.go:31

type mheap struct { lock mutex // spans: 指向mspans区域,用于映射mspan和page的关系 spans []*mspan // 指向bitmap首地址,bitmap是从高地址向低地址增长的 bitmap uintptr // 指示arena区首地址 arena_start uintptr // 指示arena区已使用地址位置 arena_used uintptr // 指示arena区末地址 arena_end uintptr central [67*2]struct { mcentral mcentral pad [sys.CacheLineSize - unsafe.Sizeof(mcentral{})%sys.CacheLineSize]byte } ... }

分配流程:

对象<=16B 的对象使用mcache的tiny分配器分配;

16B<对象<=32KB ,首先计算对象的规格大小(sizeClass,共有76种),然后使用mcache中相应规格大小的mspan分配;

对象>32KB ,直接从mheap上分配;

mcache–>mcentral–>mheap

如果mcache没有相应规格大小的mspan,则向mcentral申请

如果mcentral没有相应规格大小的mspan,则向mheap申请

如果mheap中也没有合适大小的mspan,则向操作系统申请

注:

sizeClass:比如某mspan的sizeClass为3,那么其划分的object大小就是32B,可以存储(16B,32B]大小的的对象

1550人已阅读,今天你学习了吗?

添加新回复