4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

型アサーションをswitchとifでベンチマーク取ってみる

Posted at

この記事はGo (その3) Advent Calendar 20163日目の記事です!

はじめに

最近、弊社内でプログラミング言語Goの輪読会をしています。
その中で型アサーションと型switchの部分の発表を担当しましたが、確かに見やすいけど実際のところパフォーマンスはどうなんだろう?と感じたのでベンチマークを取ってみました!
goは標準パッケージでベンチマークを取れるもの(benchmark.go)が存在しているので便利ですね♪

環境

  • OSX 10.11.6
  • プロセッサ 2.2GHz Intel Core i7
  • メモリ 16GB
  • go 1.6.3

結果

結論として、パフォーマンスは変わらないので可読性が高いswitch文を使った方が圧倒的によいなーと思いました。
ただ場合によってメモリのアロケーションが増える場合もあるので、その時はまた考える必要がありそうです。
(case文の中で引数のメソッドを使いたいような場合)

$ go test -bench . -benchmem 2>/dev/null
BenchmarkTypeSwitch-8   	  300000	      4224 ns/op	      64 B/op	       8 allocs/op
BenchmarkTypeIf-8       	  300000	      4326 ns/op	      64 B/op	       8 allocs/op

コード

今回のベンチマークでは下記のようなTypeSwitch TypeIfという関数を用意しました。
TypeSwitchの中でコメントアウトしている部分で変数への代入を行うと、それぞれのcase文の中で特定のinterfaseのメソッドを使うことができるようになります。

package main

import (
	"log"
)

func TypeSwitch(i interface{}) {
	switch i.(type) {
	//switch i := i.(type) { // 特定のinterfaceのメソッド使いたい場合はこっちのほうが良いかも。
	case bool:
		//if i{ // switch i:= i.(type)の書き方でないとコンパイルエラーになる
		//	// do...
		//}
		log.Printf("%T", i)
	case float32:
		log.Printf("%T", i)
	case float64:
		log.Printf("%T", i)
	case complex64:
		log.Printf("%T", i)
	case complex128:
		log.Printf("%T", i)
	case int:
		log.Printf("%T", i)
	case int8:
		log.Printf("%T", i)
	case int16:
		log.Printf("%T", i)
	case int32:
		log.Printf("%T", i)
	case int64:
		log.Printf("%T", i)
	case uint:
		log.Printf("%T", i)
	case uint8:
		log.Printf("%T", i)
	case uint16:
		log.Printf("%T", i)
	case uint32:
		log.Printf("%T", i)
	case uint64:
		log.Printf("%T", i)
	case uintptr:
		log.Printf("%T", i)
	case string:
		log.Printf("%T", i)
	case []byte:
		log.Printf("%T", i)
	}
}

func TypeIf(i interface{}) {
	if _, ok := i.(bool); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(float32); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(float64); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(complex64); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(complex128); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(int); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(int8); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(int16); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(int32); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(int64); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(uint8); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(uint16); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(uint32); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(uint64); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(uintptr); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.(string); ok {
		log.Printf("%T", i)
	}
	if _, ok := i.([]byte); ok {
		log.Printf("%T", i)
	}
}

参考

おわりに

型switchのコードを探してる時にBigswitchというラベルを見つけてちょっとおもしろかったです。
また気になることがあればサッとベンチマークを取って行きたいと思います。
goはtool周りが標準であるのがステキですね!

使ったコードはこちら
https://github.com/futabooo/playground/tree/master/go

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?