Skip to content

Commit e85b8db

Browse files
committed
runtime: use multiplication with overflow check for makemap
This improves performance for maps with a bucket size (key+value*8 bytes) larger than 32 bytes and removes loading a value from the maxElems array for smaller bucket sizes. name old time/op new time/op delta MakeMap/[Byte]Byte 93.5ns ± 1% 91.8ns ± 1% -1.83% (p=0.000 n=10+10) MakeMap/[Int]Int 134ns ± 1% 127ns ± 2% -5.61% (p=0.000 n=9+10) Updates #21588 Change-Id: I53f77186769c4bd0f2b90f3c6c17df643b060e39 Reviewed-on: https://go-review.googlesource.com/c/143797 Run-TryBot: Martin Möhrmann <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 93eded0 commit e85b8db

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

src/runtime/map.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ package runtime
5555

5656
import (
5757
"runtime/internal/atomic"
58+
"runtime/internal/math"
5859
"runtime/internal/sys"
5960
"unsafe"
6061
)
@@ -296,7 +297,8 @@ func makemap_small() *hmap {
296297
// If h != nil, the map can be created directly in h.
297298
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
298299
func makemap(t *maptype, hint int, h *hmap) *hmap {
299-
if hint < 0 || hint > int(maxSliceCap(t.bucket.size)) {
300+
mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
301+
if overflow || mem > maxAlloc {
300302
hint = 0
301303
}
302304

@@ -306,7 +308,8 @@ func makemap(t *maptype, hint int, h *hmap) *hmap {
306308
}
307309
h.hash0 = fastrand()
308310

309-
// find size parameter which will hold the requested # of elements
311+
// Find the size parameter B which will hold the requested # of elements.
312+
// For hint < 0 overLoadFactor returns false since hint < bucketCnt.
310313
B := uint8(0)
311314
for overLoadFactor(hint, B) {
312315
B++

src/runtime/map_benchmark_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,23 @@ func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) {
228228
func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) }
229229
func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) }
230230

231+
func BenchmarkMakeMap(b *testing.B) {
232+
b.Run("[Byte]Byte", func(b *testing.B) {
233+
var m map[byte]byte
234+
for i := 0; i < b.N; i++ {
235+
m = make(map[byte]byte, 10)
236+
}
237+
hugeSink = m
238+
})
239+
b.Run("[Int]Int", func(b *testing.B) {
240+
var m map[int]int
241+
for i := 0; i < b.N; i++ {
242+
m = make(map[int]int, 10)
243+
}
244+
hugeSink = m
245+
})
246+
}
247+
231248
func BenchmarkNewEmptyMap(b *testing.B) {
232249
b.ReportAllocs()
233250
for i := 0; i < b.N; i++ {

0 commit comments

Comments
 (0)