You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently map amortizes the growth over several inserts/deletes. This means that if we do several inserts to get map into a "growing" state and than never insert/delete anything and just iterate through map we get much higher cost of iteration, because in the "growing" state we are doing extra hashing (line 934 in map.go hash := t.hasher(k, uintptr(h.hash0)). Consider the following benchmark that adds X strings into a map and than iterates over them a lot:
//go:noinline
func iter(m map[string]string) int {
ret := 0
for _, a := range m {
ret += len(a)
}
return ret
}
func BenchmarkMap(b *testing.B) {
minSize := 50
maxSize := 60
for size := minSize; size < maxSize; size++ {
b.Run(fmt.Sprintf("input_size_%d", size), func(b *testing.B) {
m := make(map[string]string)
for i := 0; i < size; i++ {
key := make([]byte, 300)
value := make([]byte, 300)
rand.Read(key)
rand.Read(value)
m[string(key)] = string(value)
}
x := 0
for i := 0; i < b.N; i++ {
x += iter(m)
}
})
}
}
What did you expect to see?
Stable cost of iteration, growing linearly with the number of elements.
What did you see instead?
For some numbers of elements, performance is 4-5x worse:
Adding size to make fixed the issue, but this is still a cause of a significant and unexpected performance cliff. So growing map on iterations makes sense to avoid performance cliffs like this.
The text was updated successfully, but these errors were encountered:
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Currently map amortizes the growth over several inserts/deletes. This means that if we do several inserts to get map into a "growing" state and than never insert/delete anything and just iterate through map we get much higher cost of iteration, because in the "growing" state we are doing extra hashing (line 934 in map.go
hash := t.hasher(k, uintptr(h.hash0))
. Consider the following benchmark that adds X strings into a map and than iterates over them a lot:What did you expect to see?
Stable cost of iteration, growing linearly with the number of elements.
What did you see instead?
For some numbers of elements, performance is 4-5x worse:
Adding size to make fixed the issue, but this is still a cause of a significant and unexpected performance cliff. So growing map on iterations makes sense to avoid performance cliffs like this.
The text was updated successfully, but these errors were encountered: