Go map literal performance
Go Map Literals performance
During recent go code benchmarking I noticed that function which returns a map literal
// some code above
return map[string]float {
"key1": SOME_COMPUTED_ABOVE_VALUE,
"key2": SOME_COMPUTED_ABOVE_VALUE,
// more keys here
"keyN": SOME_COMPUTED_ABOVE_VALUE,
}
calls hashGrow
much more then expected.
I actually expected none cause the size of the map known as a compile time.
So I changed the code above to
// some code above
result := make(map[string]float, SIZE) // SIZE >= N
result["key1"] = SOME_COMPUTED_ABOVE_VALUE
result["key2"] = SOME_COMPUTED_ABOVE_VALUE
// more keys here
result["keyN"] = SOME_COMPUTED_ABOVE_VALUE
return result
and it actually sped up my benchmark ~1/3
To confirm the issue I developed a set of benchmarks and showed the problem
Map size | Map literal perf | Map make perf |
---|---|---|
5 | 235 ns/op | 240 ns/op |
9 | 716 ns/op | 453 ns/op |
65 | 7346 ns/op | 3401 ns/op |
513 | 59357 ns/op | 24774 ns/op |
So one can see that for sufficiently big maps we have 2x speedup.
Here are full result. This investigation is not yet over.
For example, I do not yet know why sometimes it makes 2 allocations but in other cases 3 allocations even when using make
BenchmarkMap/0003-8 6375036 187 ns/op 256 B/op 2 allocs/op
BenchmarkMap/0005-8 4897664 240 ns/op 256 B/op 2 allocs/op
BenchmarkMap/0009-8 2684498 453 ns/op 464 B/op 2 allocs/op
BenchmarkMap/0017-8 1434456 854 ns/op 954 B/op 2 allocs/op
BenchmarkMap/0033-8 807938 1609 ns/op 1868 B/op 2 allocs/op
BenchmarkMap/0065-8 375810 3401 ns/op 4176 B/op 3 allocs/op
BenchmarkMap/0129-8 198102 6541 ns/op 8272 B/op 3 allocs/op
BenchmarkMap/0257-8 102302 12072 ns/op 14417 B/op 3 allocs/op
BenchmarkMap/0513-8 50647 24774 ns/op 28752 B/op 3 allocs/op
BenchmarkMapStringLiteral/0003-8 6525012 188 ns/op 256 B/op 2 allocs/op
BenchmarkMapStringLiteral/0005-8 5099382 235 ns/op 256 B/op 2 allocs/op
BenchmarkMapStringLiteral/0009-8 1587074 716 ns/op 672 B/op 3 allocs/op
BenchmarkMapStringLiteral/0017-8 730539 1688 ns/op 1633 B/op 4 allocs/op
BenchmarkMapStringLiteral/0033-8 344728 3432 ns/op 3594 B/op 6 allocs/op
BenchmarkMapStringLiteral/0065-8 177174 7346 ns/op 8020 B/op 9 allocs/op
BenchmarkMapStringLiteral/0129-8 84253 14291 ns/op 16324 B/op 11 allocs/op
BenchmarkMapStringLiteral/0257-8 41516 28957 ns/op 30744 B/op 12 allocs/op
BenchmarkMapStringLiteral/0513-8 20548 59357 ns/op 61348 B/op 22 allocs/op
Written on November 28, 2020