How slow is using type assertions / type switches in Go, as a method of run-time type discovery?
I've heard that in C/C++ for example, discovering types at run time has bad performance. To bypass that, you usually add type members to classes, so you can compare against these instead of casting.
I haven't found a clear answer for this throughout the www.
Here's an example of what I'm asking about - Is this considered fast when compared to other type checking methodologies (like mentioned above, or others I'm not aware of)?
func question(anything interface{}) {
switch v := anything.(type) {
case string:
fmt.Println(v)
case int32, int64:
fmt.Println(v)
case SomeCustomType:
fmt.Println(v)
default:
fmt.Println("unknown")
}
}
It is very easy to write a Benchmark test to check it: http://play.golang.org/p/E9H_4K2J9-
package main
import (
"testing"
)
type myint int64
type Inccer interface {
inc()
}
func (i *myint) inc() {
*i = *i + 1
}
func BenchmarkIntmethod(b *testing.B) {
i := new(myint)
incnIntmethod(i, b.N)
}
func BenchmarkInterface(b *testing.B) {
i := new(myint)
incnInterface(i, b.N)
}
func BenchmarkTypeSwitch(b *testing.B) {
i := new(myint)
incnSwitch(i, b.N)
}
func BenchmarkTypeAssertion(b *testing.B) {
i := new(myint)
incnAssertion(i, b.N)
}
func incnIntmethod(i *myint, n int) {
for k := 0; k < n; k++ {
i.inc()
}
}
func incnInterface(any Inccer, n int) {
for k := 0; k < n; k++ {
any.inc()
}
}
func incnSwitch(any Inccer, n int) {
for k := 0; k < n; k++ {
switch v := any.(type) {
case *myint:
v.inc()
}
}
}
func incnAssertion(any Inccer, n int) {
for k := 0; k < n; k++ {
if newint, ok := any.(*myint); ok {
newint.inc()
}
}
}
EDIT Oct. 09, 2019
It appears that the methods demonstrated above are equal and have no advantage over one another. Here are the results from my machine (AMD R7 2700X, Golang v1.12.9):
BenchmarkIntmethod-16 2000000000 1.67 ns/op
BenchmarkInterface-16 1000000000 2.03 ns/op
BenchmarkTypeSwitch-16 2000000000 1.70 ns/op
BenchmarkTypeAssertion-16 2000000000 1.67 ns/op
PASS
AND AGAIN:
BenchmarkIntmethod-16 2000000000 1.68 ns/op
BenchmarkInterface-16 1000000000 2.01 ns/op
BenchmarkTypeSwitch-16 2000000000 1.66 ns/op
BenchmarkTypeAssertion-16 2000000000 1.67 ns/op
PREVIOUS RESULTS on Jan. 19, 2015
On my amd64 machine, I'm getting the following timing:
$ go test -bench=.
BenchmarkIntmethod 1000000000 2.71 ns/op
BenchmarkInterface 1000000000 2.98 ns/op
BenchmarkTypeSwitch 100000000 16.7 ns/op
BenchmarkTypeAssertion 100000000 13.8 ns/op
So it looks like accessing the method via type switch or type assertion is about 5-6 times slower than calling the method directly or via interface.
I don't know if C++ is slower or if this slowdown is tolerable for your application.