开源门户网站,wordpress用什么主机好,做外贸哪些网站好,wordpress更改主题名1.内存模型
1.1 操作系统存储模型
从上到下分别是寄存器、高速缓存、内存、磁盘#xff0c;其中越往上速度越快#xff0c;空间越小#xff0c;价格越高。
关键词是多级模型和动态切换
1.2 虚拟内存与物理内存
虚拟内存是一种内存管理技术#xff0c;允许计算机使用比…1.内存模型
1.1 操作系统存储模型
从上到下分别是寄存器、高速缓存、内存、磁盘其中越往上速度越快空间越小价格越高。
关键词是多级模型和动态切换
1.2 虚拟内存与物理内存
虚拟内存是一种内存管理技术允许计算机使用比物理内存更多的内存资源通过将部分内存存储在硬盘上的方式扩展了系统的可用内存。
1.3 分页管理
操作系统会把虚拟内存和物理内存切割成固定的尺寸于虚拟内存而言叫做“页”于物理内存而言叫“帧”原因如下
提高内存空间利用减少外部碎片内部碎片相对可控提高内外存交换的效率更细的粒度带来了更高的灵活度与虚拟内存机制呼应便于使用页表建立虚拟地址到物理地址之间的映射linux 页/帧的大小固定为4KB实践得到的经验值太大的话会增加碎片率太小的话增加分配频率影响效率
1.4 Golang内存模型
几个核心的设计要点
空间换时间一次缓存多次复用因为每次向操作系统申请内存的操作很重那么不妨一次多申请一些以备后用。Golang的堆mheap正是基于该思想产生的数据结构对于操作系统而言这是用户进程中缓存的内存对于Go进程内部堆是所有对象的内存起源。多级缓存实现无/细锁化堆是Go运行时最大的临界共享资源这意味着每次存取都要加锁很影响性能。为了解决这个问题Golang依次细化粒度建立了mcentral,mcache的模型 mheap全局的内存起源访问要加全局锁。数量只有1个mcentral每种对象大小规格对应的缓存锁的粒度仅仅局限于同一种规格里全局划分为68份。BigCache也用到了类似的思想数量有68*2个详细见2.3mcache每个P即goroutine 内核线程持有的一份内存缓存访问时没有锁。数量等于P的数量 多级规格提高利用率 page最小的存储单元借鉴操作系统分页管理的思想每个最小的存储单元也称之为页但是大小为8KBmspan最小的管理单元大小是page的整数倍从8B到80KB被划分为67种不同的规格分配对象时会根据大小映射到不同规则的mspan从中获取空间。产生的特点 根据规格大小产生了等级的制度才使得central支持细锁化消除了外部碎片但是不可避免地会有内部碎片宏观上能提高整体空间利用率
2.核心概念
2.1 内存单元mspan
mspan是Golang内存管理地最小单元大小是page地整数倍而且内部的页是连续的。
每个mspan会根据空间大小以及面向分配对象的大小被划分为不同的等级同等级的mspan会从属一个mcentral最终被组织成链表带有前后指针(prev/next)而且因为同属一个mcentral所以是基于同一把互斥锁管理。
基于bitMap辅助快速找到空闲内存块块大小为对应等级下的object大小这里用到了Ctz64算法
type mspan struct {// 标识前后节点的指针 next *mspan prev *mspan // ...// 起始地址startAddr uintptr // 包含几页页是连续的npages uintptr // 标识此前的位置都已被占用 freeindex uintptr// 最多可以存放多少个 objectnelems uintptr // number of object in the span.// bitmap 每个 bit 对应一个 object 块标识该块是否已被占用allocCache uint64// ...// 标识 mspan 等级包含 class 和 noscan 两部分信息spanclass spanClass // ...
}Ctz64算法是一种用于计算一个数的二进制表示中尾随零trailing zeros的数量的算法 2.2 内存单元等级 spanClass
mspan根据空间大小和面向分配对象的大小被划分为67种等级分别是1~67实际上隐藏的0级用于处理更大的对象
mspan等级列表font stylecolor:rgb(25, 27, 31);runtime/sizeclasses.go/font文件里 classmspan等级标识1~67bytes/obj该大小规格的对象会从这个mspan里获取空间创建对象过程中大小会上取整为8B的整数倍因此该表可以直接实现object到mspan等级的映射bytes/span该等级的mspan的总空间大小object该等级的mspan最多可以new多少个对象也就是span/objtail wastespan%obj的值max waste当一个对象被分配在某个size class中时由于对象大小与span大小不完全匹配可能导致的内存空间未被充分利用的情况
以class 3的 mspan为例class分配的object大小统一为24B只有17~24B大小的object会被分配到class3最坏情况为object 大小为17B浪费空间比如为 ((24-17)*341 8 ) / 8192 28.24%
每个object还有一个重要的属性是nocan标识了object是否含有指针在gc时是否需要展开标记。
golang里把span class 和 nocan两个信息组装为一个uint8形成完整的spanClass标识。高7位标识span等级最后一位标识nocan信息。
// A spanClass represents the size class and noscan-ness of a span.
//
// Each size class has a noscan spanClass and a scan spanClass. The
// noscan spanClass contains only noscan objects, which do not contain
// pointers and thus do not need to be scanned by the garbage
// collector.
type spanClass uint8const (numSpanClasses _NumSizeClasses 1tinySpanClass spanClass(tinySizeClass1 | 1)
)func makeSpanClass(sizeclass uint8, noscan bool) spanClass {return spanClass(sizeclass1) | spanClass(bool2int(noscan))
}func (sc spanClass) sizeclass() int8 {return int8(sc 1)
}func (sc spanClass) noscan() bool {return sc1 ! 0
}2.3 线程缓存mcache
mcache是每个goroutine独有的缓存因此没有锁。
mcache把每种span class等级的mspan各缓存了一个并且因为nocan的值也有2种有指针 无指针所以总数是2*68136个
mcache还有一个对象分配器 tiny allocator用于处理小于16B对象的内存分配。
type mcache struct {_ sys.NotInHeap// The following members are accessed on every malloc,// so they are grouped here for better caching.nextSample uintptr // trigger heap sample after allocating this many bytesscanAlloc uintptr // bytes of scannable heap allocated// Allocator cache for tiny objects w/o pointers.// See Tiny allocator comment in malloc.go.// tiny points to the beginning of the current tiny block, or// nil if there is no current tiny block.//// tiny is a heap pointer. Since mcache is in non-GCd memory,// we handle it by clearing it in releaseAll during mark// termination.//// tinyAllocs is the number of tiny allocations performed// by the P that owns this mcache.tiny uintptrtinyoffset uintptrtinyAllocs uintptr// The rest is not accessed on every malloc.alloc [numSpanClasses]*mspan // spans to allocate from, indexed by spanClassstackcache [_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
}2.4 中心缓存mcentral
每个mcentral对应一种spanclass而且聚合了该spanclass下的mspan。
mcentral下的msapn分为2个链表有空间msapn链表partial和满空间mspan链表full
每个mcentral一把锁
注意partial和full链表都包含两组mspan一组是已清扫的正在使用的spans另一组是未清扫的正在使用的spans在每个垃圾回收GC周期里这两个角色会互换。
// Central list of free objects of a given size.
type mcentral struct {_ sys.NotInHeapspanclass spanClass// partial and full contain two mspan sets: one of swept in-use// spans, and one of unswept in-use spans. These two trade// roles on each GC cycle. The unswept set is drained either by// allocation or by the background sweeper in every GC cycle,// so only two roles are necessary.//// sweepgen is increased by 2 on each GC cycle, so the swept// spans are in partial[sweepgen/2%2] and the unswept spans are in// partial[1-sweepgen/2%2]. Sweeping pops spans from the// unswept set and pushes spans that are still in-use on the// swept set. Likewise, allocating an in-use span pushes it// on the swept set.//// Some parts of the sweeper can sweep arbitrary spans, and hence// cant remove them from the unswept set, but will add the span// to the appropriate swept list. As a result, the parts of the// sweeper and mcentral that do consume from the unswept list may// encounter swept spans, and these should be ignored.partial [2]spanSet // list of spans with a free objectfull [2]spanSet // list of spans with no free objects
}2.5 全局堆缓存mheap
堆是操作系统虚拟内存的抽象以页8KB为单位其中页是作为最小内存存储单元的。
mheap可以把连续页组装成mspan。
全局内存基于bitMap标识使用情况每个bit对应一页为1标识已经被mspan组装。
通过heapArena聚合页记录了页到mspan的映射信息详见2.7
建立空间页基数树索引radix tree index辅助快速寻找空闲页详见2.6
是mcentral的持有者持有所有spanClass下的mcentral作为自身的缓存。
内存不够时向操作系统申请申请单位是heapArena64M
type mheap struct {// 堆的全局锁lock mutex// 空闲页分配器底层是多棵基数树组成的索引每棵树对应 16 GB 内存空间pages pageAlloc // 记录了所有的 mspan. 需要知道所有 mspan 都是经由 mheap使用连续空闲页组装生成的allspans []*mspan// heapAreana 数组64 位系统下二维数组容量为 [1][2^22]// 每个 heapArena 大小 64M因此理论上Golang 堆上限为 2^22*64M 256Tarenas [1 arenaL1Bits]*[1 arenaL2Bits]*heapArena// 多个 mcentral总个数为 spanClass 的个数central [numSpanClasses]struct {mcentral mcentral// 用于内存地址对齐pad [cpu.CacheLinePadSize - unsafe.Sizeof(mcentral{})%cpu.CacheLinePadSize]byte}// ...
}Golang内存模型和分配机制