Slow string concatenation

I have a code as below.

Concatenation using + is extremely slow than buffer using.

Why buffer or strings.Builder is required?

package main

import (
	"bytes"
	"fmt"
	"math/rand"
	"strings"
	"time"
)


var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}


func appendStrings() {
	total := 1503259

	result := ""

	for i := 0; i < total; i++ {
		result += RandStringRunes(10) + "/" + RandStringRunes(10) + "/" + RandStringRunes(10) + RandStringRunes(10) + "\n"

		if i%500 == 0 {
			fmt.Println("Progress: ", i, "/", total)
		}
	}

	fmt.Println(result[:100])
}

func appendStringsUsingBuffer() {
	total := 1503259

	result := ""

	var buf bytes.Buffer

	for i := 0; i < total; i++ {
		buf.WriteString(RandStringRunes(10) + "/" + RandStringRunes(10) + "/" + RandStringRunes(10) + RandStringRunes(10) + "\n")

		if i%500 == 0 {
			fmt.Println("Progress: ", i, "/", total)
		}
	}

	result = buf.String()

	fmt.Println(result[:100])
}

func appendStringsUsingBuilder() {
	total := 1503259

	result := ""

	var sb strings.Builder

	for i := 0; i < total; i++ {
		sb.WriteString(RandStringRunes(10) + "/" + RandStringRunes(10) + "/" + RandStringRunes(10) + RandStringRunes(10) + "\n")

		if i%500 == 0 {
			fmt.Println("Progress: ", i, "/", total)
		}
	}

	result = sb.String()

	fmt.Println(result[:100])
}


func main() {
	rand.Seed(time.Now().UnixNano())

	// appendStrings()
	// appendStringsUsingBuffer()
	appendStringsUsingBuilder()
}

Because concatenation using + allocates and copies, but strings.Builder amortizes allocation and avoids copying. This is in common with in every language I’ve used that has a string concatenation operator.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.