Golang--map扩容机制(含源码)

本文详细介绍了Go语言中Map的等量扩容和增量扩容机制。当溢出桶数量过多或承载因子超过6.5时,Map会触发扩容。等量扩容会在桶数量过多时新建同等大小的Map并迁移数据;增量扩容则在承载因子过高时使容量翻倍。相关源码位于go1.18/src/runtime/map.go。
摘要由CSDN通过智能技术生成

1 等量扩容

1.1 触发条件

溢出桶数量过多

  • B大于15时,以15计算,如果溢出桶 >= 2^15次方,触发等量扩容
  • B小于15时,以B计算,如果溢出桶 >= 大于2^B次方,触发等量扩容

1.2 触发结果

新建等量大小的map,将旧数据挪过去

1.3 源码

路径: 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 增量扩容

2.1 触发条件

承载因子>6.5

  • 承载因子:map元素总量/bucket数量。
  • map元素总量为:hmap中的count。
  • bucket数量:2^B

2.2 触发结果

容量翻倍,挪移数据。

2.3 源码

路径: 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))
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值