概要
Stackoverflowには Go Collective というのがあります。
The official Q&A channel for Google's Go Programming Language.
と書いてある通り、公式のQ&Aとなっていて、いい質問と回答が揃っています。
ついでなので、自分の勉強も兼ねて、ここにメモメモ。。。
今回はコレ。
サンプル
main.go
// Stackoverflow Go Collective example // // How to efficiently concatenate strings in go // // URL // - https://stackoverflow.com/questions/1760757/how-to-efficiently-concatenate-strings-in-go // // REFERENCES // - https://pkg.go.dev/strings@latest#Builder // - https://yourbasic.org/golang/measure-execution-time/ package main import ( "bytes" "log" "strings" "time" "github.com/devlights/gomy/times" ) func init() { log.SetFlags(0) } func main() { // Go 1.10 より strings.Builder が追加された。 // bytes.Buffer でも良いが、文字列の場合はこちらのほうが効率が良い。 var ( sb strings.Builder buf bytes.Buffer ) // ----- bytes.Buffer ----- // elapsed := times.Stopwatch(func(start time.Time) { for i := 0; i < 3_000_000; i++ { buf.WriteString("i") } }) log.Printf("[bytes.Buffer ] len=%d, elapsed=%v", buf.Len(), elapsed) // ----- strings.Builder ----- // elapsed = times.Stopwatch(func(start time.Time) { for i := 0; i < 3_000_000; i++ { sb.WriteString("i") } }) log.Printf("[strings.Builder] len=%d, elapsed=%v", sb.Len(), elapsed) }
Taskfile.yml
version: "3" tasks: bench: cmds: - go test -benchmem -run=^$ -bench . run: cmds: - go run -race main.go
実行すると以下のようになります。
gitpod /workspace/try-golang (master) $ task -d examples/gocollective/concatenate-strings/ run task: [run] go run -race main.go [bytes.Buffer ] len=3000000, elapsed=671.430265ms [strings.Builder] len=3000000, elapsed=575.146634ms
確かに strings.Builder の方が僅かに速いですね。
bench_test.go
ベンチ取れよって思ったので、ベンチマークも書きました。
package main import ( "bytes" "strings" "testing" ) func BenchmarkBufferConcatenate(b *testing.B) { var ( buf bytes.Buffer ) b.StartTimer() for i := 0; i < b.N; i++ { buf.WriteString("i") } b.StopTimer() b.Log(buf.Len()) } func BenchmarkStringBuilderConcatenate(b *testing.B) { var ( sb strings.Builder ) b.StartTimer() for i := 0; i < b.N; i++ { sb.WriteString("i") } b.StopTimer() b.Log(sb.Len()) }
実行すると以下のようになります。
gitpod /workspace/try-golang (master) $ task -d examples/gocollective/concatenate-strings/ bench task: [bench] go test -benchmem -run=^$ -bench . goos: linux goarch: amd64 pkg: github.com/devlights/try-golang/examples/gocollective/concatenate-strings cpu: AMD EPYC 7B13 BenchmarkBufferConcatenate-16 100000000 12.28 ns/op 2 B/op 0 allocs/op --- BENCH: BenchmarkBufferConcatenate-16 bench_test.go:20: 1 bench_test.go:20: 100 bench_test.go:20: 10000 bench_test.go:20: 1000000 bench_test.go:20: 100000000 BenchmarkStringBuilderConcatenate-16 142488498 7.035 ns/op 5 B/op 0 allocs/op --- BENCH: BenchmarkStringBuilderConcatenate-16 bench_test.go:34: 1 bench_test.go:34: 100 bench_test.go:34: 10000 bench_test.go:34: 1000000 bench_test.go:34: 100000000 bench_test.go:34: 142488498 PASS ok github.com/devlights/try-golang/examples/gocollective/concatenate-strings 3.125s
同じ傾向ですね。
参考情報
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。