The majority of the performance difference between strings concat and builder in your example is explained by memory allocation. Every loop of concat will result in a new allocation, while the builder - which uses []bytes internally - will only allocate when length equals capacity, and the newly allocated slice will be approx. twice the capacity of the old slice (see: <a href="https://golang.org/src/strings/builder.go?#L62" rel="nofollow">https://golang.org/src/strings/builder.go?#L62</a>).<p>Therefore, 500,000 rounds of concat is about 500,000 allocations, while 200,000,000 rounds of builder is ~ 27.5 allocations (=log2(200000000)).<p>I would suggest a different benchmark to approximate real world usage:<p><pre><code> func BenchmarkConcatString(b *testing.B) {
for n := 0; n < b.N; n++ {
var str string
str += "x"
str += "y"
str += "z"
}
}
func BenchmarkConcatBuilder(b *testing.B) {
for n := 0; n < b.N; n++ {
var builder strings.Builder
builder.WriteString("x")
builder.WriteString("y")
builder.WriteString("z")
builder.String()
}
}
</code></pre>
Which still shows a significant performance advantage for using builder (-40% ns/op):<p><pre><code> BenchmarkConcatString-4 20000000 93.5 ns/op
BenchmarkConcatBuilder-4 30000000 54.6 ns/op</code></pre>