From adb1e67f02fa58b13d1baf60c84556f375f6ceeb Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Mon, 29 Aug 2016 09:44:50 +1000 Subject: [PATCH] reflect: avoid zeroing memory that will be overwritten MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Avoid new'ing memory that will be overwritten by assignment. name old time/op new time/op delta Call-4 160ns ± 4% 155ns ± 2% -3.19% (p=0.003 n=10+10) FieldByName1-4 94.5ns ± 2% 95.2ns ± 1% +0.65% (p=0.026 n=9+9) FieldByName2-4 3.09µs ± 4% 3.13µs ± 2% ~ (p=0.165 n=10+10) FieldByName3-4 19.8µs ± 1% 19.9µs ± 1% ~ (p=0.395 n=10+8) InterfaceBig-4 11.6ns ± 0% 11.7ns ± 0% +0.86% (p=0.000 n=8+9) InterfaceSmall-4 11.7ns ± 0% 11.7ns ± 0% ~ (all samples are equal) New-4 26.6ns ± 0% 26.4ns ± 0% -0.64% (p=0.000 n=10+9) name old alloc/op new alloc/op delta Call-4 0.00B ±NaN% 0.00B ±NaN% ~ (all samples are equal) name old allocs/op new allocs/op delta Call-4 0.00 ±NaN% 0.00 ±NaN% ~ (all samples are equal) Change-Id: I12c85d4e65245598669dd6f66beb0744ec9b9d6d Reviewed-on: https://go-review.googlesource.com/28011 Run-TryBot: Dave Cheney Reviewed-by: Ian Lance Taylor Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/reflect/type.go | 47 +++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index 94c5d020c6..98cc9ceded 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1456,25 +1456,24 @@ func (t *rtype) ptrTo() *rtype { // Create a new ptrType starting with the description // of an *unsafe.Pointer. - p = new(ptrType) var iptr interface{} = (*unsafe.Pointer)(nil) prototype := *(**ptrType)(unsafe.Pointer(&iptr)) - *p = *prototype + pp := *prototype - p.str = resolveReflectName(newName(s, "", "", false)) + pp.str = resolveReflectName(newName(s, "", "", false)) // For the type structures linked into the binary, the // compiler provides a good hash of the string. // Create a good hash for the new string by using // the FNV-1 hash's mixing function to combine the // old hash and the new "*". - p.hash = fnv1(t.hash, '*') + pp.hash = fnv1(t.hash, '*') - p.elem = t + pp.elem = t - ptrMap.m[t] = p + ptrMap.m[t] = &pp ptrMap.Unlock() - return &p.rtype + return &pp.rtype } // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function. @@ -1852,8 +1851,7 @@ func ChanOf(dir ChanDir, t Type) Type { // Make a channel type. var ichan interface{} = (chan unsafe.Pointer)(nil) prototype := *(**chanType)(unsafe.Pointer(&ichan)) - ch := new(chanType) - *ch = *prototype + ch := *prototype ch.tflag = 0 ch.dir = uintptr(dir) ch.str = resolveReflectName(newName(s, "", "", false)) @@ -1896,8 +1894,7 @@ func MapOf(key, elem Type) Type { // Make a map type. var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) - mt := new(mapType) - *mt = **(**mapType)(unsafe.Pointer(&imap)) + mt := **(**mapType)(unsafe.Pointer(&imap)) mt.str = resolveReflectName(newName(s, "", "", false)) mt.tflag = 0 mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash)) @@ -2248,15 +2245,16 @@ func bucketOf(ktyp, etyp *rtype) *rtype { } } - b := new(rtype) - b.align = ptrSize + b := &rtype{ + align: ptrSize, + size: size, + kind: kind, + ptrdata: ptrdata, + gcdata: gcdata, + } if overflowPad > 0 { b.align = 8 } - b.size = size - b.ptrdata = ptrdata - b.kind = kind - b.gcdata = gcdata s := "bucket(" + ktyp.String() + "," + etyp.String() + ")" b.str = resolveReflectName(newName(s, "", "", false)) return b @@ -2285,8 +2283,7 @@ func SliceOf(t Type) Type { // Make a slice type. var islice interface{} = ([]unsafe.Pointer)(nil) prototype := *(**sliceType)(unsafe.Pointer(&islice)) - slice := new(sliceType) - *slice = *prototype + slice := *prototype slice.tflag = 0 slice.str = resolveReflectName(newName(s, "", "", false)) slice.hash = fnv1(typ.hash, '[') @@ -2830,8 +2827,7 @@ func ArrayOf(count int, elem Type) Type { // Make an array type. var iarray interface{} = [1]unsafe.Pointer{} prototype := *(**arrayType)(unsafe.Pointer(&iarray)) - array := new(arrayType) - *array = *prototype + array := *prototype array.str = resolveReflectName(newName(s, "", "", false)) array.hash = fnv1(typ.hash, '[') for n := uint32(count); n > 0; n >>= 8 { @@ -3071,13 +3067,14 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin offset += -offset & (ptrSize - 1) // build dummy rtype holding gc program - x := new(rtype) - x.align = ptrSize + x := &rtype{ + align: ptrSize, + size: offset, + ptrdata: uintptr(ptrmap.n) * ptrSize, + } if runtime.GOARCH == "amd64p32" { x.align = 8 } - x.size = offset - x.ptrdata = uintptr(ptrmap.n) * ptrSize if ptrmap.n > 0 { x.gcdata = &ptrmap.data[0] } else { -- 2.48.1