mirror of
https://github.com/golang/go
synced 2024-11-23 17:40:03 -07:00
reflect, runtime: optimize Name method
Several minor changes that remove a good chunk of the overhead added to the reflect Name method over the 1.7 cycle, as seen from the non-SSA architectures. In particular, there are ~20 fewer instructions in reflect.name.name on 386, and the method now qualifies for inlining. The simple JSON decoding benchmark on darwin/386: name old time/op new time/op delta CodeDecoder-8 49.2ms ± 0% 48.9ms ± 1% -0.77% (p=0.000 n=10+9) name old speed new speed delta CodeDecoder-8 39.4MB/s ± 0% 39.7MB/s ± 1% +0.77% (p=0.000 n=10+9) On darwin/amd64 the effect is less pronounced: name old time/op new time/op delta CodeDecoder-8 38.9ms ± 0% 38.7ms ± 1% -0.38% (p=0.005 n=10+10) name old speed new speed delta CodeDecoder-8 49.9MB/s ± 0% 50.1MB/s ± 1% +0.38% (p=0.006 n=10+10) Counterintuitively, I get much more useful benchmark data out of my MacBook Pro than a linux workstation with more expensive Intel chips. While the laptop has fewer cores and an active GUI, the single-threaded performance is significantly better (nearly 1.5x decoding throughput) so the differences are more pronounced. For #16117. Change-Id: I4e0cc1cc2d271d47d5127b1ee1ca926faf34cabf Reviewed-on: https://go-review.googlesource.com/24510 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
b75b0630fe
commit
ed9362f769
@ -466,15 +466,13 @@ func (n name) tagLen() int {
|
|||||||
|
|
||||||
func (n name) name() (s string) {
|
func (n name) name() (s string) {
|
||||||
if n.bytes == nil {
|
if n.bytes == nil {
|
||||||
return ""
|
return
|
||||||
}
|
|
||||||
nl := n.nameLen()
|
|
||||||
if nl == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
b := (*[4]byte)(unsafe.Pointer(n.bytes))
|
||||||
|
|
||||||
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
hdr := (*stringHeader)(unsafe.Pointer(&s))
|
||||||
hdr.Data = unsafe.Pointer(n.data(3))
|
hdr.Data = unsafe.Pointer(&b[3])
|
||||||
hdr.Len = nl
|
hdr.Len = int(b[1])<<8 | int(b[2])
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,16 +660,10 @@ type typeOff int32 // offset to an *rtype
|
|||||||
type textOff int32 // offset from top of text section
|
type textOff int32 // offset from top of text section
|
||||||
|
|
||||||
func (t *rtype) nameOff(off nameOff) name {
|
func (t *rtype) nameOff(off nameOff) name {
|
||||||
if off == 0 {
|
|
||||||
return name{}
|
|
||||||
}
|
|
||||||
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
|
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *rtype) typeOff(off typeOff) *rtype {
|
func (t *rtype) typeOff(off typeOff) *rtype {
|
||||||
if off == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
|
return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,14 +170,18 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
|
|||||||
return name{}
|
return name{}
|
||||||
}
|
}
|
||||||
base := uintptr(ptrInModule)
|
base := uintptr(ptrInModule)
|
||||||
var md *moduledata
|
for md := &firstmoduledata; md != nil; md = md.next {
|
||||||
for next := &firstmoduledata; next != nil; next = next.next {
|
if base >= md.types && base < md.etypes {
|
||||||
if base >= next.types && base < next.etypes {
|
res := md.types + uintptr(off)
|
||||||
md = next
|
if res > md.etypes {
|
||||||
break
|
println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes))
|
||||||
|
throw("runtime: name offset out of range")
|
||||||
|
}
|
||||||
|
return name{(*byte)(unsafe.Pointer(res))}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if md == nil {
|
|
||||||
|
// No module found. see if it is a run time name.
|
||||||
reflectOffsLock()
|
reflectOffsLock()
|
||||||
res, found := reflectOffs.m[int32(off)]
|
res, found := reflectOffs.m[int32(off)]
|
||||||
reflectOffsUnlock()
|
reflectOffsUnlock()
|
||||||
@ -189,13 +193,6 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
|
|||||||
throw("runtime: name offset base pointer out of range")
|
throw("runtime: name offset base pointer out of range")
|
||||||
}
|
}
|
||||||
return name{(*byte)(res)}
|
return name{(*byte)(res)}
|
||||||
}
|
|
||||||
res := md.types + uintptr(off)
|
|
||||||
if res > md.etypes {
|
|
||||||
println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes))
|
|
||||||
throw("runtime: name offset out of range")
|
|
||||||
}
|
|
||||||
return name{(*byte)(unsafe.Pointer(res))}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *_type) nameOff(off nameOff) name {
|
func (t *_type) nameOff(off nameOff) name {
|
||||||
|
Loading…
Reference in New Issue
Block a user