mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: avoid allocation when interface's contents are not addressable
See issue 4949 for a full explanation. Allocs go from 1 to zero in the non-addressable case. Fixes #4949. BenchmarkInterfaceBig 90 14 -84.01% BenchmarkInterfaceSmall 14 14 +0.00% R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/12646043
This commit is contained in:
parent
d2bff757f6
commit
94179d61ab
2 changed files with 36 additions and 1 deletions
|
|
@ -3419,6 +3419,40 @@ func BenchmarkFieldByName3(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type S struct {
|
||||||
|
i1 int64
|
||||||
|
i2 int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkInterfaceBig(b *testing.B) {
|
||||||
|
v := ValueOf(S{})
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.Interface()
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllocsInterfaceBig(t *testing.T) {
|
||||||
|
v := ValueOf(S{})
|
||||||
|
if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
|
||||||
|
t.Errorf("allocs:", allocs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkInterfaceSmall(b *testing.B) {
|
||||||
|
v := ValueOf(int64(0))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
v.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllocsInterfaceSmall(t *testing.T) {
|
||||||
|
v := ValueOf(int64(0))
|
||||||
|
if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
|
||||||
|
t.Errorf("allocs:", allocs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
|
// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
|
||||||
// The basic usage is:
|
// The basic usage is:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -1004,7 +1004,8 @@ func valueInterface(v Value, safe bool) interface{} {
|
||||||
eface.typ = v.typ
|
eface.typ = v.typ
|
||||||
eface.word = v.iword()
|
eface.word = v.iword()
|
||||||
|
|
||||||
if v.flag&flagIndir != 0 && v.typ.size > ptrSize {
|
// Don't need to allocate if v is not addressable or fits in one word.
|
||||||
|
if v.flag&flagAddr != 0 && v.typ.size > ptrSize {
|
||||||
// eface.word is a pointer to the actual data,
|
// eface.word is a pointer to the actual data,
|
||||||
// which might be changed. We need to return
|
// which might be changed. We need to return
|
||||||
// a pointer to unchanging data, so make a copy.
|
// a pointer to unchanging data, so make a copy.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue