Go map 大小

如何得到一个 map 占用了多少内存

go get github.com/520MianXiangDuiXiang520/MapSize
package main

import (
	"fmt"
	"github.com/520MianXiangDuiXiang520/MapSize"
)

func main() {
	m := make(map[int]struct{})
	for i := 0; i < 100; i++ {
		m[i] = struct{}{}
	}
	fmt.Println(mapsize.Size(m)) // 1416
}

思路:

map 底层是 runtime.hmap 只需要使用 unsafe 将 map 指针对应的内存强转就可以得到 map 申请的桶的个数了,乘以键值的大小就可以算出内存占用情况:

func Size[K comparable, V any](m map[K]V) int64 {
	var zeroK K
	var zeroValue V
	keySize := unsafe.Sizeof(zeroK)
	valueSize := unsafe.Sizeof(zeroValue)
	vo := reflect.ValueOf(m)
	hm := (*hmap)(unsafe.Pointer(vo.Pointer()))
	bn := 1<<hm.B + uintptr(hm.noverflow)
	bz := unsafe.Sizeof(bmap{}) + (keySize+valueSize)*bucketCnt
	return int64(unsafe.Sizeof(hmap{}) + bz*bn)
}

注意:由于 noverflow 并不是真实的溢出桶数量,所以这种方法得到内存占用并不完全准确,但 map 本身的阔缩容用的也是 noverflow 所以与实际情况并不会差很多,通过 pprof 测试也几乎一致

你可能感兴趣的:(golang,开发语言,后端)