Goでslice結合するとき、append(slice1, slice2…)するのと
— inari111 (@inari111) 2018年2月14日
for _, s := range slice2 {
slice1 = append(slice1, s)
}
1つずつappendするのどっちがパフォーマンスいいんだろう
sliceを結合するときに、どういう書き方をするのがパフォーマンスがいいのか気になって検証してみた。 検証したのは2パターン。
パターン1: slice同士を結合
func appendSlice(n int) []string { sliceA := make([]string, n) sliceB := make([]string, n) for i := 1; i <= n; i++ { sliceA = append(sliceA, "a") sliceB = append(sliceB, "b") } sliceA = append(sliceA, sliceB...) return sliceA }
パターン2: forで回しながらappend
func appendSlice2(n int) []string { sliceA := make([]string, n) sliceB := make([]string, n) for _, s := range sliceB { sliceA = append(sliceA, s) } return sliceA }
パフォーマンスを計測するためにベンチマークを書く。
package main import "testing" func BenchmarkAppendSlice(b *testing.B) { b.ResetTimer() appendSlice(b.N) } func BenchmarkAppendSlice2(b *testing.B) { b.ResetTimer() appendSlice2(b.N) }
パターン1のベンチマーク
$ go test -count 10 -test.bench BenchmarkAppendSlice BenchmarkAppendSlice-8 2000000 631 ns/op BenchmarkAppendSlice-8 2000000 596 ns/op BenchmarkAppendSlice-8 2000000 631 ns/op BenchmarkAppendSlice-8 2000000 595 ns/op BenchmarkAppendSlice-8 2000000 602 ns/op BenchmarkAppendSlice-8 2000000 600 ns/op BenchmarkAppendSlice-8 2000000 596 ns/op BenchmarkAppendSlice-8 2000000 598 ns/op BenchmarkAppendSlice-8 2000000 597 ns/op BenchmarkAppendSlice-8 2000000 596 ns/op PASS ok github.com/inari111/test 18.915s
パターン2のベンチマーク
$ go test -count 10 -test.bench BenchmarkAppendSlice2 BenchmarkAppendSlice2-8 5000000 253 ns/op BenchmarkAppendSlice2-8 10000000 243 ns/op BenchmarkAppendSlice2-8 10000000 206 ns/op BenchmarkAppendSlice2-8 10000000 204 ns/op BenchmarkAppendSlice2-8 10000000 198 ns/op BenchmarkAppendSlice2-8 10000000 205 ns/op BenchmarkAppendSlice2-8 10000000 200 ns/op BenchmarkAppendSlice2-8 10000000 201 ns/op BenchmarkAppendSlice2-8 10000000 201 ns/op BenchmarkAppendSlice2-8 10000000 202 ns/op PASS ok github.com/inari111/test 22.293s
まとめ
パターン1のslice同士の結合のほうがパフォーマンスよさそう。
もし間違ってたら教えていただけると嬉しい。