package cat
import (
"bytes"
)
// catは += 演算子をつかって文字列を結合します
func cat(ss ...string) string {
var r string
for _, s := range ss {
r += s
}
return r
}
// bufは bytes.Buffer をつかって文字列を結合します
func buf(ss ...string) string {
var b bytes.Buffer
for _, s := range ss {
// NOTICE: エラーは無視しています
b.WriteString(s)
}
return b.String()
}
package cat
import (
"testing"
)
func seed(n int) []string {
s := make([]string, 0, n)
for i := 0; i < n; i++ {
s = append(s, "a")
}
return s
}
func bench(b *testing.B, n int, f func(...string) string) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
f(seed(n)...)
}
}
func BenchmarkCat3(b *testing.B) { bench(b, 3, cat) }
func BenchmarkBuf3(b *testing.B) { bench(b, 3, buf) }
func BenchmarkCat100(b *testing.B) { bench(b, 100, cat) }
func BenchmarkBuf100(b *testing.B) { bench(b, 100, buf) }
func BenchmarkCat10000(b *testing.B) { bench(b, 10000, cat) }
func BenchmarkBuf10000(b *testing.B) { bench(b, 10000, buf) }
go test -bench .
goos: darwin
goarch: amd64
BenchmarkCat3-4 10000000 207 ns/op 54 B/op 3 allocs/op
BenchmarkBuf3-4 10000000 227 ns/op 163 B/op 3 allocs/op
BenchmarkCat100-4 200000 8057 ns/op 7520 B/op 100 allocs/op
BenchmarkBuf100-4 500000 2694 ns/op 2160 B/op 4 allocs/op
BenchmarkCat10000-4 100 14908131 ns/op 53327792 B/op 10000 allocs/op
BenchmarkBuf10000-4 10000 216301 ns/op 211424 B/op 11 allocs/op
- ループが実行された回数
- 1ループごとの所要時間、1ループごとのメモリ
- アロケーションされたバイト数、1ループごとの
- アロケーション回数が表示されています。
この結果からわかること
- +=による文字列結合は、結合する要素数が少ないときはbytes.Bufferと遜色ないパフォーマンスである。しかし、要素数が増えると処理が遅くなり、アロケーションも増える
- bytes.Bufferによる文字列結合は、+= を使った文字列結合と比べると要素数が増えても性能が出ている。アロケーションも少ない