Commit e85b8db6 authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Martin Möhrmann

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 <martisch@uos.de>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 93eded02
...@@ -55,6 +55,7 @@ package runtime ...@@ -55,6 +55,7 @@ package runtime
import ( import (
"runtime/internal/atomic" "runtime/internal/atomic"
"runtime/internal/math"
"runtime/internal/sys" "runtime/internal/sys"
"unsafe" "unsafe"
) )
...@@ -296,7 +297,8 @@ func makemap_small() *hmap { ...@@ -296,7 +297,8 @@ func makemap_small() *hmap {
// If h != nil, the map can be created directly in h. // If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket. // If h.buckets != nil, bucket pointed to can be used as the first bucket.
func makemap(t *maptype, hint int, h *hmap) *hmap { func makemap(t *maptype, hint int, h *hmap) *hmap {
if hint < 0 || hint > int(maxSliceCap(t.bucket.size)) { mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
if overflow || mem > maxAlloc {
hint = 0 hint = 0
} }
...@@ -306,7 +308,8 @@ func makemap(t *maptype, hint int, h *hmap) *hmap { ...@@ -306,7 +308,8 @@ func makemap(t *maptype, hint int, h *hmap) *hmap {
} }
h.hash0 = fastrand() h.hash0 = fastrand()
// find size parameter which will hold the requested # of elements // Find the size parameter B which will hold the requested # of elements.
// For hint < 0 overLoadFactor returns false since hint < bucketCnt.
B := uint8(0) B := uint8(0)
for overLoadFactor(hint, B) { for overLoadFactor(hint, B) {
B++ B++
......
...@@ -228,6 +228,23 @@ func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) { ...@@ -228,6 +228,23 @@ func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) {
func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) } func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) }
func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) } func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) }
func BenchmarkMakeMap(b *testing.B) {
b.Run("[Byte]Byte", func(b *testing.B) {
var m map[byte]byte
for i := 0; i < b.N; i++ {
m = make(map[byte]byte, 10)
}
hugeSink = m
})
b.Run("[Int]Int", func(b *testing.B) {
var m map[int]int
for i := 0; i < b.N; i++ {
m = make(map[int]int, 10)
}
hugeSink = m
})
}
func BenchmarkNewEmptyMap(b *testing.B) { func BenchmarkNewEmptyMap(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment