diff options
author | David Crawshaw <crawshaw@golang.org> | 2016-06-27 21:37:19 -0400 |
---|---|---|
committer | David Crawshaw <crawshaw@golang.org> | 2016-06-28 12:28:05 +0000 |
commit | ed9362f769626b1cdaf2eb1da63d5f25cadc979b (patch) | |
tree | 8710f5df82c87fde7a2b5b1cc8ea17ad3943a457 /src/runtime/type.go | |
parent | b75b0630fe6d8f66f937f78f15f540b5b6dab24f (diff) | |
download | go-ed9362f769626b1cdaf2eb1da63d5f25cadc979b.tar.gz go-ed9362f769626b1cdaf2eb1da63d5f25cadc979b.zip |
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>
Diffstat (limited to 'src/runtime/type.go')
-rw-r--r-- | src/runtime/type.go | 41 |
1 files changed, 19 insertions, 22 deletions
diff --git a/src/runtime/type.go b/src/runtime/type.go index 49d3855e4d..5ef11a4fc4 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -170,32 +170,29 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name { return name{} } base := uintptr(ptrInModule) - var md *moduledata - for next := &firstmoduledata; next != nil; next = next.next { - if base >= next.types && base < next.etypes { - md = next - break - } - } - if md == nil { - reflectOffsLock() - res, found := reflectOffs.m[int32(off)] - reflectOffsUnlock() - if !found { - println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:") - for next := &firstmoduledata; next != nil; next = next.next { - println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) + for md := &firstmoduledata; md != nil; md = md.next { + if base >= md.types && base < md.etypes { + 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") } - throw("runtime: name offset base pointer out of range") + return name{(*byte)(unsafe.Pointer(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") + + // No module found. see if it is a run time name. + reflectOffsLock() + res, found := reflectOffs.m[int32(off)] + reflectOffsUnlock() + if !found { + println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:") + for next := &firstmoduledata; next != nil; next = next.next { + println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) + } + throw("runtime: name offset base pointer out of range") } - return name{(*byte)(unsafe.Pointer(res))} + return name{(*byte)(res)} } func (t *_type) nameOff(off nameOff) name { |