Does a type assertion / type switch have bad performance / is slow in Go?
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.
I wanted to verify siritinga's answer by myself, and check whether removing the check in TypeAssertion would make it faster. I added the following in their benchmark:
func incnAssertionNoCheck(any Inccer, n int) {
for k := 0; k < n; k++ {
any.(*myint).inc()
}
}
func BenchmarkTypeAssertionNoCheck(b *testing.B) {
i := new(myint)
incnAssertionNoCheck(i, b.N)
}
and re-ran the benchmarks on my machine.
BenchmarkIntmethod-12 2000000000 1.77 ns/op
BenchmarkInterface-12 1000000000 2.30 ns/op
BenchmarkTypeSwitch-12 500000000 3.76 ns/op
BenchmarkTypeAssertion-12 2000000000 1.73 ns/op
BenchmarkTypeAssertionNoCheck-12 2000000000 1.72 ns/op
So it seems that the cost of doing a type switch went down significantly from Go 1.4 (that I assume siritinga used) to Go 1.6 (that I'm using): from 5-6 times slower to less than 2 times slower for a type switch, and no slow-down for a type assertion (with or without check).
My Results using Go 1.9
BenchmarkIntmethod-4 1000000000 2.42 ns/op
BenchmarkInterface-4 1000000000 2.84 ns/op
BenchmarkTypeSwitch-4 1000000000 2.29 ns/op
BenchmarkTypeAssertion-4 1000000000 2.14 ns/op
BenchmarkTypeAssertionNoCheck-4 1000000000 2.34 ns/op
Type Assertion is much faster now, but the most interesting removing the type check makes it slow.