Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a type assertion / type switch have bad performance / is slow in Go?

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")     } } 
like image 409
Ory Band Avatar asked Jan 19 '15 12:01

Ory Band


People also ask

Is type assertion bad practice?

It weakens Type Safety Because of this, type assertions are considered an anti-pattern or code smell unless the user is absolutely sure what they are doing. For example, in some advanced/fancy use case of type hacking, tooling or when the typings of a third-party library is not accurate.

What is Type assertion in GO What does it do?

Type assertions in Golang provide access to the exact type of variable of an interface. If already the data type is present in the interface, then it will retrieve the actual data type value held by the interface. A type assertion takes an interface value and extracts from it a value of the specified explicit type.

What is type switch in Golang?

A switch is a multi-way branch statement used in place of multiple if-else statements but can also be used to find out the dynamic type of an interface variable.


1 Answers

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.

like image 176
siritinga Avatar answered Sep 22 '22 05:09

siritinga