我想知道uint8或uint16 Go映射键是否将存储为1/2字节,或者它们将具有uint32/64内存分配,而不管指定的内容是否更小?
最佳答案
map 是Go中的哈希图,其内部结构并不复杂。常识告诉您 key 大小应该有所不同,但是由于这不在语言规范中,因此请自己进行测量。
检查How to get memory size of variable in Go?以了解如何测量任意变量的大小。
例如创建一个测试:
const size = 250
func getMap8(size int) map[uint8]uint16 {
m := make(map[uint8]uint16, size)
for i := uint8(0); i < uint8(size); i++ {
m[i] = uint16(i)
}
return m
}
func getMap16(size int) map[uint16]uint16 {
m := make(map[uint16]uint16, size)
for i := uint16(0); i < uint16(size); i++ {
m[i] = i
}
return m
}
func getMap32(size int) map[uint32]uint16 {
m := make(map[uint32]uint16, size)
for i := uint32(0); i < uint32(size); i++ {
m[i] = uint16(i)
}
return m
}
func getMap64(size int) map[uint64]uint16 {
m := make(map[uint64]uint16, size)
for i := uint64(0); i < uint64(size); i++ {
m[i] = uint16(i)
}
return m
}
func Benchmark8(b *testing.B) {
for n := 0; n < b.N; n++ {
getMap8(size)
}
}
func Benchmark16(b *testing.B) {
for n := 0; n < b.N; n++ {
getMap16(size)
}
}
func Benchmark32(b *testing.B) {
for n := 0; n < b.N; n++ {
getMap32(size)
}
}
func Benchmark64(b *testing.B) {
for n := 0; n < b.N; n++ {
getMap64(size)
}
}
使用go test -bench . -benchmem
运行它,输出为:Benchmark8-8 95862 11210 ns/op 3188 B/op 4 allocs/op
Benchmark16-8 107731 11017 ns/op 3572 B/op 4 allocs/op
Benchmark32-8 150126 8496 ns/op 4980 B/op 4 allocs/op
Benchmark64-8 144655 8959 ns/op 6644 B/op 4 allocs/op
因此,如果键大小较小,则映射大小确实会较小,但是很明显,键和值大小共同决定了最终大小。包含250个条目的
map[uint8]uint16
类型的映射的大小约为3188字节,uint16
key 类型的映射为3572字节,uint32
key 类型的映射为4980字节,uint64
key 类型的映射为6644字节。
关于dictionary - 分配给映射键多少内存?即map [uint16] uint16是每个键2个字节还是存储为uint32/64?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65688365/