cmd/compile: do not allocate bucket for non-escaping map

For map with hint larger than BUCKETSIZE, makemap ignore allocated
bucket and allocate buckets itself. So do not allocate bucket in
this case, save us the cost of zeroing+assignment to the bucket.

name                            old time/op    new time/op    delta
NewEmptyMap-12                    3.89ns ± 4%    3.88ns ± 2%    ~     (p=0.939 n=19+20)
NewSmallMap-12                    23.3ns ± 3%    23.1ns ± 2%    ~     (p=0.307 n=18+17)
NewEmptyMapHintLessThan8-12       6.43ns ± 3%    6.31ns ± 2%  -1.72%  (p=0.000 n=19+18)
NewEmptyMapHintGreaterThan8-12     159ns ± 2%     150ns ± 1%  -5.79%  (p=0.000 n=20+18)

Benchmark run with commit ab7c174 reverted, see #38314.

Fixes #20184

Change-Id: Ic021f57454c3a0dd50601d73bbd77b8faf8d93b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/227458
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Cuong Manh Le 2020-04-08 03:08:21 +07:00
parent 346d7d273c
commit 98b6c6aca6
2 changed files with 38 additions and 5 deletions

View File

@ -1247,12 +1247,23 @@ opswitch:
// are stored with an indirection. So max bucket size is 2048+eps.
if !Isconst(hint, CTINT) ||
hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) <= 0 {
// In case hint is larger than BUCKETSIZE runtime.makemap
// will allocate the buckets on the heap, see #20184
//
// if hint <= BUCKETSIZE {
// var bv bmap
// b = &bv
// h.buckets = b
// }
nif := nod(OIF, nod(OLE, hint, nodintconst(BUCKETSIZE)), nil)
nif.SetLikely(true)
// var bv bmap
bv := temp(bmap(t))
zero = nod(OAS, bv, nil)
zero = typecheck(zero, ctxStmt)
init.Append(zero)
nif.Nbody.Append(zero)
// b = &bv
b := nod(OADDR, bv, nil)
@ -1260,8 +1271,11 @@ opswitch:
// h.buckets = b
bsym := hmapType.Field(5).Sym // hmap.buckets see reflect.go:hmap
na := nod(OAS, nodSym(ODOT, h, bsym), b)
na = typecheck(na, ctxStmt)
init.Append(na)
nif.Nbody.Append(na)
nif = typecheck(nif, ctxStmt)
nif = walkstmt(nif)
init.Append(nif)
}
}

View File

@ -513,3 +513,22 @@ func BenchmarkMapInterfacePtr(b *testing.B) {
BoolSink = m[key]
}
}
var (
hintLessThan8 = 7
hintGreaterThan8 = 32
)
func BenchmarkNewEmptyMapHintLessThan8(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = make(map[int]int, hintLessThan8)
}
}
func BenchmarkNewEmptyMapHintGreaterThan8(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = make(map[int]int, hintGreaterThan8)
}
}