如何得到一个 map 占用了多少内存
go get github.com/520MianXiangDuiXiang520/MapSize
package mainimport ("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 Kvar zeroValue VkeySize := 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)*bucketCntreturn int64(unsafe.Sizeof(hmap{}) + bz*bn)
}
注意:由于 noverflow 并不是真实的溢出桶数量,所以这种方法得到内存占用并不完全准确,但 map 本身的阔缩容用的也是 noverflow 所以与实际情况并不会差很多,通过 pprof 测试也几乎一致