Table of contents
1 Equivalent expansion
1.1 Trigger conditions
Too many overflow buckets
- When B is greater than 15, it is calculated as 15. If the bucket overflows>=2^15 power, triggering equal expansion
- When B is less than 15, calculated as B, if the bucket overflows>=Greater than 2^B power, triggers equal expansion
1.2 Trigger results
Create a new map of the same size and move the old data there
1.3 Source code
Path: go1.18/src/runtime/map.go
// overflow buckets 太多
func tooManyOverflowBuckets(noverflow uint16, B uint8) bool {
// If the threshold is too low, we do extraneous work.
// If the threshold is too high, maps that grow and shrink can hold on to lots of unused memory.
// "too many" means (approximately) as many overflow buckets as regular buckets.
// See incrnoverflow for more details.
if B > 15 {
B = 15
}
// The compiler doesn't see here that B < 16; mask B to generate shorter shift code.
return noverflow >= uint16(1)<<(B&15)
}
2 Incremental expansion
2.1 Trigger conditions
Load factor >6.5
- Bearing factor: total number of map elements/number of buckets.
- The total number of map elements is: count in hmap.
- Number of buckets: 2^B
2.2 Trigger results
Double the capacity and move the data.
2.3 Source code
Path: go1.18/src/runtime/map.go
func overLoadFactor(count int, B uint8) bool {
return count > bucketCnt && uintptr(count) > loadFactorNum*(bucketShift(B)/loadFactorDen)
//人话:当count大于8且承载因子大于6.5时可满足要求
}
count (
bucketCntBits = 3
bucketCnt = 1 << bucketCntBits
loadFactorNum = 13
loadFactorDen = 2
)
// bucketShift returns 1<<b, optimized for code generation.
// 翻译,返回2的B次方
func bucketShift(b uint8) uintptr {
// Masking the shift amount allows overflow checks to be elided.
return uintptr(1) << (b & (goarch.PtrSize*8 - 1))
}