Welcome to the Part-2 of Speed Up Your API’s
Today, we will go through the common and most ignored use case
i.e. string concatenation
Concatenating two strings using the plus operator (+) is the easiest approach when building a string, but it is not the most efficient way to do so. This is because a string is a primitive data type that is immutable. Whenever we need to perform operations on a string, it creates a copy of it and performs operations on the copy, eventually leading to the allocation of more memory.
Therefore, Performing operations on a slice of bytes is fast,mutable and consumes less memory.
Go Lang have two different built-in packages to do it efficiently
1. strings (strings.Builder)
2. bytes (bytes.Buffer)
Both of these types use slice of bytes ([]byte) to build a string.
However bytes.Buffer provides read operations as well, while strings.Builder is specifically designed for building strings.
Let’s jump in and compare the latency and memory allocation of string concatenation using different methods.
Implementations :-
package concat
import (
"bytes"
"strings"
)
func stringConcatUsingPlus(){
var a string
for i:=1;i<100;i++{
a+="a"
}
}
func stringConcatUsingStringBuilder(){
var a strings.Builder
for i:=1;i<100;i++{
a.WriteString("a")
}
a.Reset()
}
func stringConcatUsingBytesBuffer(){
var a bytes.Buffer
for i:=1;i<100;i++{
a.WriteString("a")
}
a.Reset()
}
Benchmark testing :-
package concat
import "testing"
func BenchmarkConcatUsingPlus(b *testing.B) {
b.ReportAllocs()
for i := 1; i < b.N; i++ {
stringConcatUsingPlus()
}
}
func BenchmarkConcatUsingStringBuilder(b *testing.B) {
b.ReportAllocs()
for i := 1; i < b.N; i++ {
stringConcatUsingStringBuilder()
}
}
func BenchmarkConcatUsingBytesBuffer(b *testing.B) {
b.ReportAllocs()
for i := 1; i < b.N; i++ {
stringConcatUsingBytesBuffer()
}
}
Results :-
- using Plus (+) operator:-
go test -bench=BenchmarkConcatUsingPlus -benchtime=5s -cpu=1 -count=5
BenchmarkConcatUsingPlus 1000000 5883 ns/op 5552 B/op 97 allocs/op
BenchmarkConcatUsingPlus 1000000 10980 ns/op 5552 B/op 97 allocs/op
BenchmarkConcatUsingPlus 509296 13421 ns/op 5552 B/op 97 allocs/op
BenchmarkConcatUsingPlus 460945 13591 ns/op 5552 B/op 97 allocs/op
BenchmarkConcatUsingPlus 487670 13144 ns/op 5552 B/op 97 allocs/op
PASS
ok medium/concat 37.490s
2. using strings.Builder:-
go test -bench=BenchmarkConcatUsingStringBuilder -benchtime=5s -cpu=1 -count=5
BenchmarkConcatUsingStringBuilder 16297044 375.9 ns/op 248 B/op 4 allocs/op
BenchmarkConcatUsingStringBuilder 15305996 833.0 ns/op 248 B/op 4 allocs/op
BenchmarkConcatUsingStringBuilder 6742114 936.3 ns/op 248 B/op 4 allocs/op
BenchmarkConcatUsingStringBuilder 6047766 915.6 ns/op 248 B/op 4 allocs/op
BenchmarkConcatUsingStringBuilder 7051450 899.7 ns/op 248 B/op 4 allocs/op
PASS
ok medium//concat 41.220s
3. using bytes.Buffer:-
go test -bench=BenchmarkConcatUsingBytesBuffer -benchtime=5s -cpu=1 -count=5
cpu: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
BenchmarkConcatUsingBytesBuffer 7736871 804.7 ns/op 207 B/op 1 allocs/op
BenchmarkConcatUsingBytesBuffer 7095190 1852 ns/op 207 B/op 1 allocs/op
BenchmarkConcatUsingBytesBuffer 3209696 1816 ns/op 207 B/op 1 allocs/op
BenchmarkConcatUsingBytesBuffer 3161494 1882 ns/op 207 B/op 1 allocs/op
BenchmarkConcatUsingBytesBuffer 3289645 1881 ns/op 207 B/op 1 allocs/op
PASS
ok medium/concat 45.199s
Based on the benchmark results mentioned above, it is clear that the plus (+) operator allocated 24 times more memory than the strings.Builder implementation and 96 times more memory than the bytes.Buffer implementation. Therefore, it is apparent that the plus operator is not an efficient option for string concatenation.
However, strings.Builder allocated four times more memory than bytes.Buffer. But when it comes to latency, strings.Builder was two times more efficient. Therefore, it depends on the use case whether to use strings.Builder or bytes.Buffer.
When it comes to pure string building, usage of String.Builder is preferred.
Please feel free to add any comments/suggestion/ mistakes etc…👍
For part — 1 please refer to https://medium.com/@saiteja180/speed-up-your-apis-8f006d8bde61