I'm trying to efficiently test whether an interface{} implements a given function and my solution is to create an interface with just this function and then check whether the interface{} implements this single function interface. The two options here seem to be either using reflection or a type assertion. Both seem to have identical behaviour however there is a large speed difference.
Looking at the code for Value.Implements() it does a linear scan over the functions defined on the value and compares them against the interface. The type assertion however just seems to do a constant time comparison (independent of the number of functions in the interface).
Is there a reason why Implements() doesn't just do a type assertion?
Benchmark:
package benchmarks
import (
"reflect"
"testing"
)
type ITest interface {
Foo()
}
type Base struct{}
func (Base) A() {}
func (Base) B() {}
func (Base) C() {}
func (Base) D() {}
func (Base) E() {}
func (Base) F() {}
func (Base) G() {}
func (Base) H() {}
func (Base) I() {}
func (Base) J() {}
var Interface = reflect.TypeOf((*ITest)(nil)).Elem()
func BenchmarkReflection(b *testing.B) {
var iface interface{}
iface = Base{}
for i := 0; i < b.N; i++ {
if reflect.TypeOf(iface).Implements(Interface) {
b.FailNow()
}
}
}
func BenchmarkAssertion(b *testing.B) {
var iface interface{}
iface = Base{}
for i := 0; i < b.N; i++ {
if _, ok := iface.(ITest); ok {
b.FailNow()
}
}
}
Results:
go test -run=XXX -bench=. so_test.go
goos: linux
goarch: amd64
BenchmarkReflection-8 10000000 208 ns/op
BenchmarkAssertion-8 200000000 9.24 ns/op
PASS
ok command-line-arguments 5.115s
Aucun commentaire:
Enregistrer un commentaire