Skip to content

reflect: possible saved allocation in Value.Interface #4949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rsc opened this issue Mar 1, 2013 · 4 comments
Closed

reflect: possible saved allocation in Value.Interface #4949

rsc opened this issue Mar 1, 2013 · 4 comments
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented Mar 1, 2013

from private mail:

I've noticed that calling reflect.Value's Interface method is slower if the value being
reflected is larger than a word. It appears that this is due to an extra memory alloc,
but it seems like this should only be necessary if the reflect.Value is addressable.

As an example:

type S struct {
    i1 int64
    i2 int64
}

func BenchmarkInterfaceBig(b *testing.B) {
    v := reflect.ValueOf(S{})
    for i := 0; i < b.N; i++ {
        v.Interface()
    }
}

func BenchmarkInterfaceSmall(b *testing.B) {
    v := reflect.ValueOf(int64(0))
    for i := 0; i < b.N; i++ {
        v.Interface()
    }
}
 
BenchmarkInterfaceBig   20000000            84.6 ns/op        16 B/op          1 allocs/op
BenchmarkInterfaceSmall 100000000           23.2 ns/op         0 B/op          0 allocs/op

Since reflect.ValueOf(S{}) isn't addressable, it seems like it shouldn't have to do an
alloc. I took a look src/pkg/reflect/value.go and it seems that it allocs for the
following case (line 953 on tip): 

   if v.flag&flagIndir != 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.
      ptr := unsafe_New(v.typ)
      memmove(ptr, unsafe.Pointer(eface.word), v.typ.size)
      eface.word = iword(ptr)
   }

Should "v.flag&flagIndir != 0" instead be "v.flag&flagAddr !=
0"? I might be misinterpreting this code, but it seems like we can reuse the data
if it's not addressable.
@rsc
Copy link
Contributor Author

rsc commented Mar 12, 2013

Comment 1:

[The time for maybe has passed.]

Labels changed: removed go1.1maybe.

@rsc
Copy link
Contributor Author

rsc commented Jul 30, 2013

Comment 2:

Labels changed: added go1.2maybe.

@rsc
Copy link
Contributor Author

rsc commented Jul 30, 2013

Comment 3:

Labels changed: added feature.

@robpike
Copy link
Contributor

robpike commented Aug 9, 2013

Comment 4:

This issue was closed by revision 94179d6.

Status changed to Fixed.

@rsc rsc added fixed labels Aug 9, 2013
@rsc rsc added this to the Go1.2 milestone Apr 14, 2015
@rsc rsc removed the go1.2maybe label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants