array/sliceに対する存在確認関数のベンチマーク


2 min read
array/sliceに対する存在確認関数のベンチマーク

Pythonでいうところの、次の様な条件式を実現する関数を書きたかった。

ls = ["foo", "bar", "baz"]
s = "baz"

if s in ls:
    print("FOOBAR!")

対象がリストの時、普段なら普通にfor文を回すのですが、今回やりたかったのは定数値の一覧にあるかどうか、だったのと、定数の数も少なかったので、とりあえずで以下の様に実装していました。

func something(s string) error {
    if s != "foo" && s != "bar" && s != "baz" {
        return errors.New("value invalid")
    }
}

流石に雑すぎるので、リファクタリングしよう、と思ったのですが、「はて、for文挟んだら遅くなったりしないだろうか」などと考えてしまったのでベンチマークを取りました。

TL; DR

素直にfor文を回しても大して問題はなさそう

result

今回取ったベンチマークは6種類です。

  • for-range文を回す
  • for文を回す
  • map[string]struct{}を集合として取り扱ってみる
  • &&, ||でつなぐ
  • switch文を使う
  • sort.SearchStrings()を使う

6番目のsort.SearchStrings()を使う方法はstackoverflowに書いてあった方法で、二分探索をしてくれるというのでやってみました。

結果は次の通り。

BenchmarkInByForRange-4            	200000000	         9.34 ns/op	       0 B/op	       0 allocs/op
BenchmarkInByFor-4                 	100000000	        10.1 ns/op	       0 B/op	       0 allocs/op
BenchmarkInByMap-4                 	200000000	         7.79 ns/op	       0 B/op	       0 allocs/op
BenchmarkInByAnd-4                 	1000000000	         2.85 ns/op	       0 B/op	       0 allocs/op
BenchmarkInBySwitch-4              	2000000000	         1.39 ns/op	       0 B/op	       0 allocs/op
BenchmarkInBySortSearchStrings-4   	10000000	       179 ns/op	      32 B/op	       1 allocs/op

まぁ予想通りではあるものの、sort.SearchStrings()を使う方法は遅いですね。これはこの関数の「事前にリストがソート済みであること」という条件のために関数内でソートをしてるからだと思われます。(実際、ソート済みのリストを使って、関数内でソートをしないようにすると1/4くらいにはなる)

一番速かったのはswitch文を使ったやつで、これも予想通り(Go言語のswitchさん、すごく速いのは知っていた)。

とはいえ、(sort.SearchString()は除いて)せいぜい一桁ナノ秒の三倍程度しか違わないので、よほどのことが無ければ普通にfor文を回す方法でも問題ないかな、という程度の速度差でした。


Amazon EKSがGAだと言うので触ってみた
Previous article

Amazon EKSがGAだと言うので触ってみた

AWSのmanaged Kubernetesで、これまでプライベートベータだったElastic Container Service for KubernetesがGAになったということなので、さくっとクラスタを作成してみました。[1] 参考にしたのはAWS公式、EKSのGetting Started Guideです。 まずはEKSのページを見てみようとしたところ・・・ ぶっ壊れてますね!これはなんかアレですね。 gettext的なのが上手くいっていないように見えるので、画面下から英語にしてみます。 無事、正しいと思われるページが表示されました。 なんか、How it worksの説明の図がちょっとぼやけて見えるのは環境のせいでしょうか。 扨、

Future Pattern
Next article

Future Pattern

Future Patternは非同期処理パターンの一つで、ある処理を別のスレッドなどで実行し、結果を後で(=未来で)受け取るような処理に用いられるデザインパターンです。 特徴としては、外側に見えている関数などの処理を実行するオブジェクトは、処理を別スレッドに委譲し、後で結果を得ることの出来るFutureと呼ばれるオブジェクトを即座にメインロジックへと返却することです。 言葉で書いても、何だかよくわからないので、コードを見てみましょう。 /* package, import part */ func main() { in := make(chan int) out := Double(in)


GO TOP

🎉 You've successfully subscribed to something tech.!
OK