以下内容仅个人理解整理,仅供参考
在go1.18版本之后(含1.18)go slice append相比之前版本growslice函数已经发生变化,
在Go 1.18 Release Notes中提到
The built-in function append now uses a slightly different formula when deciding how much to grow a slice when it must allocate a new underlying array. The new formula is less prone to sudden transitions in allocation behavior.
以下是1.18中runtime.growslice函数实现,只截取主要代码
1 | func growslice(et *_type, old slice, cap int) slice { |
以下是1.17版本runtime.growslice函数实现
1 | func growslice(et *_type, old slice, cap int) slice { |
可以看出在 Go 1.18 中,扩容策略 (不考虑内存对齐的情况下) 变成了:
如果期望容量大于当前容量的两倍就会使用期望容量
如果当前切片的长度小于 256 就会将容量翻倍
如果当前切片的长度大于 256 就会每次增加 25% 的同时再增加 192(256 的 3/4),直到新容量大于期望容量
按照注释的说法是新的公式 newcap += (newcap + 3*threshold) / 4 会使得容量的变化更加平滑。
我们可以看到1.17版本采用的公式是而且临界值是1024 newcap += newcap / 4