Skip to content

Instantly share code, notes, and snippets.

@rhcarvalho
Last active August 29, 2015 14:27
Show Gist options
  • Select an option

  • Save rhcarvalho/abb12fa958f3e83537cf to your computer and use it in GitHub Desktop.

Select an option

Save rhcarvalho/abb12fa958f3e83537cf to your computer and use it in GitHub Desktop.
Compare sorting structs and pointer to structs
$ go test -bench . -benchmem
testing: warning: no tests to run
PASS
BenchmarkVal5 10000000 161 ns/op 32 B/op 1 allocs/op
BenchmarkPtr5 10000000 152 ns/op 32 B/op 1 allocs/op
BenchmarkValFromPtr5 1000000 2280 ns/op 1312 B/op 2 allocs/op
BenchmarkPtrFromVal5 3000000 334 ns/op 80 B/op 2 allocs/op
BenchmarkVal50 300000 4120 ns/op 32 B/op 1 allocs/op
BenchmarkPtr50 500000 3174 ns/op 32 B/op 1 allocs/op
BenchmarkValFromPtr50 100000 19084 ns/op 12320 B/op 2 allocs/op
BenchmarkPtrFromVal50 300000 6024 ns/op 448 B/op 2 allocs/op
BenchmarkVal500 20000 66041 ns/op 32 B/op 1 allocs/op
BenchmarkPtr500 30000 55028 ns/op 32 B/op 1 allocs/op
BenchmarkValFromPtr500 5000 254824 ns/op 122912 B/op 2 allocs/op
BenchmarkPtrFromVal500 10000 109946 ns/op 4128 B/op 2 allocs/op
BenchmarkVal5k 2000 893099 ns/op 32 B/op 1 allocs/op
BenchmarkPtr5k 2000 842924 ns/op 32 B/op 1 allocs/op
BenchmarkValFromPtr5k 500 3688927 ns/op 1163296 B/op 2 allocs/op
BenchmarkPtrFromVal5k 1000 1693813 ns/op 40992 B/op 2 allocs/op
BenchmarkVal50k 100 12503727 ns/op 32 B/op 1 allocs/op
BenchmarkPtr50k 50 23618415 ns/op 32 B/op 1 allocs/op
BenchmarkValFromPtr50k 30 48661713 ns/op 11608096 B/op 2 allocs/op
BenchmarkPtrFromVal50k 50 27468791 ns/op 401440 B/op 2 allocs/op
ok 97.521s
package test
import (
"math/rand"
"sort"
"testing"
"time"
)
type Blob struct {
Name string
Value int
CreationTimestamp time.Time
ptr1 *Blob
ptr2 *Blob
ptr3 *Blob
ptr4 *Blob
ptr5 *Blob
ptr6 *Blob
ptr7 *Blob
ptr8 *Blob
ptr9 *Blob
ptr10 *Blob
ptr11 *Blob
ptr12 *Blob
ptr13 *Blob
ptr14 *Blob
ptr15 *Blob
ptr16 *Blob
ptr17 *Blob
ptr18 *Blob
ptr19 *Blob
ptr20 *Blob
ptr21 *Blob
ptr22 *Blob
ptr23 *Blob
}
type BlobSliceByCreationTimestamp []Blob
func (s BlobSliceByCreationTimestamp) Len() int {
return len(s)
}
func (s BlobSliceByCreationTimestamp) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s BlobSliceByCreationTimestamp) Less(i, j int) bool {
return s[i].CreationTimestamp.Before(s[j].CreationTimestamp)
}
type BlobPointerSliceByCreationTimestamp []*Blob
func (s BlobPointerSliceByCreationTimestamp) Len() int {
return len(s)
}
func (s BlobPointerSliceByCreationTimestamp) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s BlobPointerSliceByCreationTimestamp) Less(i, j int) bool {
return s[i].CreationTimestamp.Before(s[j].CreationTimestamp)
}
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func RandStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func newRandomBlob() Blob {
return Blob{
RandStringBytes(100 + rand.Intn(5000)),
rand.Intn(987654),
time.Now().Add(time.Duration(rand.Int31()) * time.Microsecond),
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
&Blob{},
}
}
func newRandomBlobSlice(size int) []Blob {
s := make([]Blob, size)
for i := range s {
s[i] = newRandomBlob()
}
return s
}
func newRandomBlobPointerSlice(size int) []*Blob {
s := make([]*Blob, size)
for i := range s {
blob := newRandomBlob()
s[i] = &blob
}
return s
}
// sort []Blob without conversion
func benchVal(b *testing.B, size int) {
// initialize data
s := newRandomBlobSlice(size)
// ignore time spent on initialization
b.ResetTimer()
for i := 0; i < b.N; i++ {
sort.Sort(BlobSliceByCreationTimestamp(s))
}
}
// sort []*Blob without conversion
func benchPtr(b *testing.B, size int) {
// initialize data
ps := newRandomBlobPointerSlice(size)
// ignore time spent on initialization
b.ResetTimer()
for i := 0; i < b.N; i++ {
sort.Sort(BlobPointerSliceByCreationTimestamp(ps))
}
}
// sort []Blob with conversion from []*Blob
func benchValFromPtr(b *testing.B, size int) {
// initialize data
ps := newRandomBlobPointerSlice(size)
// ignore time spent on initialization
b.ResetTimer()
for i := 0; i < b.N; i++ {
s := make([]Blob, len(ps))
for i := range ps {
s[i] = *ps[i]
}
sort.Sort(BlobSliceByCreationTimestamp(s))
}
}
// sort []*Blob with conversion []Blob
func benchPtrFromVal(b *testing.B, size int) {
// initialize data
s := newRandomBlobSlice(size)
// ignore time spent on initialization
b.ResetTimer()
for i := 0; i < b.N; i++ {
ps := make([]*Blob, len(s))
for i := range s {
ps[i] = &s[i]
}
sort.Sort(BlobPointerSliceByCreationTimestamp(ps))
}
}
func BenchmarkVal5(b *testing.B) { benchVal(b, 5) }
func BenchmarkPtr5(b *testing.B) { benchPtr(b, 5) }
func BenchmarkValFromPtr5(b *testing.B) { benchValFromPtr(b, 5) }
func BenchmarkPtrFromVal5(b *testing.B) { benchPtrFromVal(b, 5) }
func BenchmarkVal50(b *testing.B) { benchVal(b, 50) }
func BenchmarkPtr50(b *testing.B) { benchPtr(b, 50) }
func BenchmarkValFromPtr50(b *testing.B) { benchValFromPtr(b, 50) }
func BenchmarkPtrFromVal50(b *testing.B) { benchPtrFromVal(b, 50) }
func BenchmarkVal500(b *testing.B) { benchVal(b, 500) }
func BenchmarkPtr500(b *testing.B) { benchPtr(b, 500) }
func BenchmarkValFromPtr500(b *testing.B) { benchValFromPtr(b, 500) }
func BenchmarkPtrFromVal500(b *testing.B) { benchPtrFromVal(b, 500) }
func BenchmarkVal5k(b *testing.B) { benchVal(b, 5000) }
func BenchmarkPtr5k(b *testing.B) { benchPtr(b, 5000) }
func BenchmarkValFromPtr5k(b *testing.B) { benchValFromPtr(b, 5000) }
func BenchmarkPtrFromVal5k(b *testing.B) { benchPtrFromVal(b, 5000) }
func BenchmarkVal50k(b *testing.B) { benchVal(b, 50000) }
func BenchmarkPtr50k(b *testing.B) { benchPtr(b, 50000) }
func BenchmarkValFromPtr50k(b *testing.B) { benchValFromPtr(b, 50000) }
func BenchmarkPtrFromVal50k(b *testing.B) { benchPtrFromVal(b, 50000) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment