Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.5k views
in Technique[技术] by (71.8m points)

dictionary - How much memory is allocated to map keys? ie will map[uint16]uint16 be 2 bytes per key or stored as uint32/64 regardless?

I'm wondering if uint8 or uint16 Go map keys will be stored as 1/2 bytes or they will have uint32/64 memory allocations regardless of specifying something smaller?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Maps are hashmaps in Go, their internals is non-trivial. Common sense tells the key size should make a difference, but since this is not in the language specification, measure it yourself.

Check How to get memory size of variable in Go? for how to measure size of arbitrary variables.

For example create a test:

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)
    }
}

Running it with go test -bench . -benchmem, the output is:

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

So the map size is indeed smaller if the key size is smaller, but obviously the key and value size together determine the final size.

Size of a map of type map[uint8]uint16 with 250 entries is about 3188 bytes, a map with uint16 key type is 3572 bytes, a map with uint32 key type is 4980 bytes, and a map with uint64 key type is 6644 bytes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...