go内存的一些问题

huanglan1213 · · 757 次点击
##### 问题1 - sizeclass 代表对象大小的级别,每个级别对象的大小是固定的,共67个级别 0是给大对象用的,其他给小对象用。 - spanclass 对象分为包含指针和不包含指针的,所以spanclass共134个级别。是sizeclass的两倍。一个spanclass中包含了sizeclass和nosan(是否包含指针) - 不同的span,根据其spanclass,来计算该span需要的page数量,然后按page的数量向页分配器申请指定数量的连续的页,来组成一个span。span会根据其对应spanclass的sizeclass,将span分成一个个对象。同一个span中对象的大小都一样的。 ``` npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) // span需要的page数量 size := uintptr(class_to_size[c.spanclass.sizeclass()]) // span中每个对象的大小 ``` ##### 问题2 - 楼上说的对
#2
更多评论
* 内存块span的sizeclass指的是什么,和page的个数有关系吗 * span通过splanclass标识属于哪种规格的span,golang的span规格一共有67种,具体查看. `src/runtime/sizeclasses.go` 另外,最低位标示是否是一个noscan的span,高7位标示属于哪一种类型,创建一个SpanClass函数如下。每一个span 是跟page数量有关系的。从源码mspan `src/runtime/mheap.go`中也可以看出来 ```golang func makeSpanClass(sizeclass uint8, noscan bool) spanClass { return spanClass(sizeclass<<1) | spanClass(bool2int(noscan)) } ``` * 从内存分配的角度来说, 一个大对象是至少32K,而一个page默认的是4k 一个大对象就是至少8个page 这样对吗 * golang一个page的大小是:8KB * 一个大对象至少是page的整数倍,从`go/src/runtime/malloc.go` 中`largeAlloc` 可以看出 ```golang func largeAlloc(size uintptr, needzero bool, noscan bool) *mspan { // print("largeAlloc size=", size, "\n") if size+_PageSize < size { throw("out of memory") } //页的整数倍, size >> _PageShift 相当于除8192 npages := size >> _PageShift if size&_PageMask != 0 { npages++ } // Deduct credit for this span allocation and sweep if // necessary. mHeap_Alloc will also sweep npages, so this only // pays the debt down to npage pages. deductSweepCredit(npages*_PageSize, npages) s := mheap_.alloc(npages, makeSpanClass(0, noscan), needzero) if s == nil { throw("out of memory") } s.limit = s.base() + size heapBitsForAddr(s.base()).initSpan(s) return s } ```
#1