Goでベンチマークを測ってみた

Go

はじめに

Goで関数のパフォーマンスを測ってみたいと思い、調べて使ってみました。

コード

文字列をループで回して結合する関数
stringsのJoinで結合する関数
どちらのほうがパフォーマンスがいいか計測してみます。

package main

import "strings"

func ConcatenateStrings(strs []string) string {
    var result string
    for _, str := range strs {
        result += str
    }
    return result
}

func JoinStrings(strs []string) string {
    return strings.Join(strs, "")
}

func main() {
    // main関数には実行コードがなくても大丈夫です
}

ここでは、1000個の配列テストデータを作成して、それを対象関数に渡しています。
testing.Bがベンチマーク用のパッケージになります。

package main

import (
    "testing"
)

func generateTestData(n int) []string {
    strs := make([]string, n)
    for i := 0; i < n; i++ {
        strs[i] = "test"
    }
    return strs
}

func BenchmarkConcatenateStrings(b *testing.B) {
    strs := generateTestData(1000)
    for i := 0; i < b.N; i++ {
        ConcatenateStrings(strs)
    }
}

func BenchmarkJoinStrings(b *testing.B) {
    strs := generateTestData(1000)
    for i := 0; i < b.N; i++ {
        JoinStrings(strs)
    }
}

動かしてみる

3105や141476は、実行した回数
ns/opは、1回あたりの実行に掛かったナノ秒
B/opは、1回あたりのアロケーションで確保したメモリ容量
allocs/opは、1回あたりのアロケーション回数

go test -bench=. -benchmem

実行速度的にもメモリ的にも、strings.Join()の方が優秀ということが分かった。

goos: darwin
goarch: amd64
pkg: github.com/xxxxx/xxxxx
cpu: Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
BenchmarkConcatenateStrings-4               3105            402025 ns/op         2137578 B/op        999 allocs/op
BenchmarkJoinStrings-4                    141476              7990 ns/op            4096 B/op          1 allocs/op
PASS
ok      github.com/xxxxx/xxxxx   3.652s