Skip to content

Instantly share code, notes, and snippets.

@anvinjain
Created July 4, 2018 05:53
Show Gist options
  • Save anvinjain/92c1c48848f59ad494f98d90f752a7fd to your computer and use it in GitHub Desktop.
Save anvinjain/92c1c48848f59ad494f98d90f752a7fd to your computer and use it in GitHub Desktop.
Golang Byte Array creation: append vs bytes.Join Benchmark
package main
import (
"testing"
"bytes"
)
func TestBytesAppendIsEquivalentToJoin(t *testing.T) {
prefix := []byte("announce")
sep := "/"
peerType := []byte("s")
type serializedPeer []byte
pk := serializedPeer("jackandjill")
ihRaw := []byte("helloworld0123456789")
type InfoHash [20]byte
infoHashFromBytes := func(b []byte) InfoHash {
if len(b) != 20 {
panic("infohash must be 20 bytes")
}
var buf [20]byte
copy(buf[:], b)
return InfoHash(buf)
}
ih := infoHashFromBytes(ihRaw)
data:= &byteArrayParts{
sep: []byte(sep),
p1: prefix,
p2: ih[:],
p3: peerType,
p4: pk,
}
k1 := generateByteArrayUsingAppend(data)
k2 := generateByteArrayUsingJoin(data)
if bytes.Compare(k1, k2) != 0 {
t.Fatal("both keys are not equal")
}
}
func BenchmarkByteAppend(b *testing.B) {
runByteArrayBenchmark(b, generateByteArrayUsingAppend)
}
func BenchmarkByteJoin(b *testing.B) {
runByteArrayBenchmark(b, generateByteArrayUsingJoin)
}
type byteArrayParts struct {
sep []byte
p1 []byte
p2 []byte
p3 []byte
p4 []byte
}
func generateByteArrayUsingAppend(data *byteArrayParts) []byte {
k := make([]byte, 0, len(data.sep) * 3 + len(data.p1) + len(data.p2) + len(data.p3) + len(data.p4))
k = append(k, data.p1...)
k = append(k, data.sep...)
k = append(k, data.p2...)
k = append(k, data.sep...)
k = append(k, data.p3...)
k = append(k, data.sep...)
k = append(k, data.p4...)
return k
}
func generateByteArrayUsingJoin(data *byteArrayParts) []byte {
k := bytes.Join([][]byte{
data.p1,
data.p2,
data.p3,
data.p4,
}, []byte(data.sep))
return k
}
func runByteArrayBenchmark(b *testing.B, ef func(data *byteArrayParts) []byte) {
data := &byteArrayParts{
sep: []byte("/"),
p1: []byte("announce"),
p2: []byte("helloworld0123456789"),
p3: []byte("s"),
p4: []byte("jackandjill"),
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ret := ef(data)
if len(ret) == 0 {
b.Fatal("empty byte array received")
}
}
b.StopTimer()
}
@anvinjain
Copy link
Author

goos: darwin
goarch: amd64
pkg: learning_go
20000000 61.5 ns/op #BenchmarkByteAppend
20000000 76.4 ns/op #BenchmarkByteJoin
PASS

BenchmarkByteJoin is 24% slower on my local setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment