Skip to content

Instantly share code, notes, and snippets.

@gosamplesdev
Created October 31, 2021 11:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gosamplesdev/3a319617bd3afb8b9b47edc3fcf29d5d to your computer and use it in GitHub Desktop.
Save gosamplesdev/3a319617bd3afb8b9b47edc3fcf29d5d to your computer and use it in GitHub Desktop.
A benchmark comparing different string concatenation methods in Go (Golang). See more on https://gosamples.dev/concatenate-strings/
package benchmark
import (
"bytes"
"fmt"
"strings"
"testing"
)
const (
hello = "hello"
gosamples = "https://gosamples.dev"
)
func generateStrings(withSeparator bool) (data []string, size int) {
for i := 0; i < 100; i++ {
data = append(data, hello)
size += len(hello)
if withSeparator {
data = append(data, " ")
size++
}
data = append(data, gosamples)
size += len(gosamples)
if withSeparator {
data = append(data, " ")
size++
}
}
if withSeparator {
data = data[:len(data)-1]
size--
}
return data, size
}
func BenchmarkPlusOperatorUnknownSize(b *testing.B) {
data, _ := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
for _, d := range data {
s += d
}
_ = s
}
}
func BenchmarkSprintfKnownSize(b *testing.B) {
data, _ := generateStrings(false)
var interfaceData []interface{}
for _, d := range data {
interfaceData = append(interfaceData, d)
}
format := strings.Repeat("%s ", len(interfaceData))
format = strings.TrimSuffix(format, " ")
var s string
for n := 0; n < b.N; n++ {
s = fmt.Sprintf(format, interfaceData...)
_ = s
}
}
func BenchmarkStringBuilderUnknownSize(b *testing.B) {
data, _ := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
var builder strings.Builder
for _, s := range data {
builder.WriteString(s)
}
s = builder.String()
_ = s
}
}
func BenchmarkStringBuilderKnownSize(b *testing.B) {
data, size := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
var builder strings.Builder
builder.Grow(size)
for _, s := range data {
builder.WriteString(s)
}
s = builder.String()
_ = s
}
}
func BenchmarkJoinKnownSize(b *testing.B) {
data, _ := generateStrings(false)
var s string
for n := 0; n < b.N; n++ {
s = strings.Join(data, " ")
_ = s
}
}
func BenchmarkBytesBufferUnknownSize(b *testing.B) {
data, _ := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
var buffer bytes.Buffer
for _, s := range data {
buffer.WriteString(s)
}
s = buffer.String()
_ = s
}
}
func BenchmarkBytesBufferKnownSize(b *testing.B) {
data, size := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
var buffer bytes.Buffer
buffer.Grow(size)
for _, s := range data {
buffer.WriteString(s)
}
s = buffer.String()
_ = s
}
}
func BenchmarkByteSliceUnknownSize(b *testing.B) {
data, _ := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
var byteSlice []byte
for _, s := range data {
byteSlice = append(byteSlice, []byte(s)...)
}
s = string(byteSlice)
_ = s
}
}
func BenchmarkByteSliceKnownSize(b *testing.B) {
data, size := generateStrings(true)
var s string
for n := 0; n < b.N; n++ {
byteSlice := make([]byte, 0, size)
for _, s := range data {
byteSlice = append(byteSlice, []byte(s)...)
}
s = string(byteSlice)
_ = s
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment