1 回答
TA贡献1802条经验 获得超4个赞
简答
它正在舍入切片容量以填充分配的内存块。
长答案
让我们来看看 Go1.5.1 源代码:
https://github.com/golang/go/blob/f2e4c8b5fb3660d793b2c545ef207153db0a34b1/src/cmd/compile/internal/gc/walk.go#L2895告诉我们append(l1, l2...)扩展为
s := l1
if n := len(l1) + len(l2) - cap(s); n > 0 {
s = growslice_n(s, n)
}
s = s[:len(l1)+len(l2)]
memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
我们感兴趣的部分growslice_n,在那里定义:https : //github.com/golang/go/blob/f2e4c8b5fb3660d793b2c545ef207153db0a34b1/src/runtime/slice.go#L36
再深入一点,我们发现:
newcap := old.cap
if newcap+newcap < cap {
newcap = cap
} else {
for {
if old.len < 1024 {
newcap += newcap
} else {
newcap += newcap / 4
}
if newcap >= cap {
break
}
}
}
/* [...] */
capmem := roundupsize(uintptr(newcap) * uintptr(et.size))
newcap = int(capmem / uintptr(et.size))
roundupsize在那里定义:https : //github.com/golang/go/blob/f2e4c8b5fb3660d793b2c545ef207153db0a34b1/src/runtime/msize.go#L178
// Returns size of the memory block that mallocgc will allocate if you ask for the size.
func roundupsize(size uintptr) uintptr {
if size < _MaxSmallSize {
if size <= 1024-8 {
return uintptr(class_to_size[size_to_class8[(size+7)>>3]])
} else {
return uintptr(class_to_size[size_to_class128[(size-1024+127)>>7]])
}
}
if size+_PageSize < size {
return size
}
return round(size, _PageSize)
}
它是在那里介绍的:https : //groups.google.com/forum/#!topic/golang-codereviews/bFGtI4Cpb_M
增长切片时要考虑分配的内存块的大小。
- 1 回答
- 0 关注
- 198 浏览
添加回答
举报