1
0
mirror of https://github.com/golang/go synced 2024-11-26 03:27:58 -07: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:
Rob Pike 2013-08-09 10:49:01 +10:00
parent d2bff757f6
commit 94179d61ab
2 changed files with 36 additions and 1 deletions

View File

@ -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.
// The basic usage is:
//

View File

@ -1004,7 +1004,8 @@ func valueInterface(v Value, safe bool) interface{} {
eface.typ = v.typ
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,
// which might be changed. We need to return
// a pointer to unchanging data, so make a copy.