-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
goos: linux | ||
goarch: amd64 | ||
pkg: github.com/prashantv/go-bench/sorted_vs_heap | ||
cpu: 13th Gen Intel(R) Core(TM) i5-13600KF | ||
BenchmarkSorted/1_shuffled_elems 34914072 35.70 ns/op | ||
BenchmarkSorted/1_sorted_elems 32636758 36.06 ns/op | ||
BenchmarkSorted/10_shuffled_elems 2861283 417.3 ns/op | ||
BenchmarkSorted/10_sorted_elems 3316832 360.2 ns/op | ||
BenchmarkSorted/100_shuffled_elems 48640 24599 ns/op | ||
BenchmarkSorted/100_sorted_elems 102871 11621 ns/op | ||
BenchmarkSorted/1000_shuffled_elems 909 1315247 ns/op | ||
BenchmarkSorted/1000_sorted_elems 1603 746310 ns/op | ||
BenchmarkHeap/1_shuffled_elems 97103852 12.06 ns/op | ||
BenchmarkHeap/1_sorted_elems 96106923 12.42 ns/op | ||
BenchmarkHeap/10_shuffled_elems 6392421 188.5 ns/op | ||
BenchmarkHeap/10_sorted_elems 6908209 173.0 ns/op | ||
BenchmarkHeap/100_shuffled_elems 385483 3120 ns/op | ||
BenchmarkHeap/100_sorted_elems 420507 2816 ns/op | ||
BenchmarkHeap/1000_shuffled_elems 14010 85408 ns/op | ||
BenchmarkHeap/1000_sorted_elems 16514 72562 ns/op | ||
PASS | ||
ok github.com/prashantv/go-bench/sorted_vs_heap 22.644s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module github.com/prashantv/go-bench/sorted_vs_heap | ||
|
||
go 1.21.1 | ||
|
||
require github.com/stretchr/testify v1.8.4 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package main | ||
|
||
import ( | ||
"container/heap" | ||
"fmt" | ||
"math/rand" | ||
"sort" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type sortedSlice []int | ||
|
||
func newSortedSlice() *sortedSlice { return &sortedSlice{} } | ||
func (ss sortedSlice) Len() int { return len(ss) } | ||
func (ss sortedSlice) Less(i, j int) bool { return ss[i] < ss[j] } | ||
func (ss sortedSlice) Swap(i, j int) { ss[i], ss[j] = ss[j], ss[i] } | ||
|
||
func (ss *sortedSlice) PushV(v int) { | ||
*ss = append(*ss, v) | ||
sort.Sort(*ss) | ||
} | ||
|
||
func (ss *sortedSlice) PopV() int { | ||
v := (*ss)[0] | ||
*ss = (*ss)[1:] | ||
return v | ||
} | ||
|
||
type heapSlice []int | ||
|
||
func newHeapSlice() *heapSlice { return &heapSlice{} } | ||
func (h heapSlice) Len() int { return len(h) } | ||
func (h heapSlice) Less(i, j int) bool { return h[i] < h[j] } | ||
func (h heapSlice) Swap(i, j int) { h[i], h[j] = h[j], h[i] } | ||
|
||
func (h *heapSlice) Push(v any) { | ||
*h = append(*h, v.(int)) | ||
} | ||
|
||
func (h *heapSlice) Pop() any { | ||
old := *h | ||
n := len(old) | ||
x := old[n-1] | ||
*h = old[0 : n-1] | ||
return x | ||
} | ||
|
||
func (h *heapSlice) PushV(v int) { | ||
heap.Push(h, v) | ||
} | ||
|
||
func (h *heapSlice) PopV() int { | ||
return heap.Pop(h).(int) | ||
} | ||
|
||
type Stack interface { | ||
PushV(v int) | ||
PopV() int | ||
Len() int | ||
} | ||
|
||
func BenchmarkSorted(b *testing.B) { | ||
runBenchmarks[*sortedSlice](b, newSortedSlice) | ||
} | ||
|
||
func TestSorted(t *testing.T) { | ||
runTests[*sortedSlice](t, newSortedSlice) | ||
} | ||
func BenchmarkHeap(b *testing.B) { | ||
runBenchmarks[*heapSlice](b, newHeapSlice) | ||
} | ||
|
||
func TestHeap(t *testing.T) { | ||
runTests[*heapSlice](t, newHeapSlice) | ||
} | ||
|
||
func runBenchmarks[S Stack](b *testing.B, newFn func() S) { | ||
for _, numElems := range []int{1, 10, 100, 1000} { | ||
elems := randElems(numElems) | ||
b.Run(fmt.Sprintf("%v shuffled elems", numElems), func(b *testing.B) { | ||
s := newFn() | ||
for i := 0; i < b.N; i++ { | ||
for _, v := range elems { | ||
s.PushV(v) | ||
} | ||
for range elems { | ||
s.PopV() | ||
} | ||
} | ||
}) | ||
|
||
b.Run(fmt.Sprintf("%v sorted elems", numElems), func(b *testing.B) { | ||
s := newFn() | ||
for i := 0; i < b.N; i++ { | ||
for j := 0; j < numElems; j++ { | ||
s.PushV(j) | ||
} | ||
for j := 0; j < numElems; j++ { | ||
s.PopV() | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func runTests[S Stack](t *testing.T, newFn func() S) { | ||
t.Run("single element", func(t *testing.T) { | ||
s := newFn() | ||
for i := 0; i < 100; i++ { | ||
s.PushV(i) | ||
assert.Equal(t, 1, s.Len()) | ||
assert.Equal(t, i, s.PopV()) | ||
assert.Equal(t, 0, s.Len()) | ||
} | ||
}) | ||
|
||
t.Run("multiple push/pop", func(t *testing.T) { | ||
push := []int{10, 5, 6, 3, 2, 8, 4, 9, 7, 1, 0} | ||
s := newFn() | ||
for _, v := range push { | ||
s.PushV(v) | ||
} | ||
|
||
// Pop some elements | ||
for i := 0; i < 5; i++ { | ||
assert.Equal(t, i, s.PopV()) | ||
} | ||
|
||
// Then push them back | ||
for i := 0; i < 5; i++ { | ||
s.PushV(4 - i) | ||
} | ||
|
||
// Push all | ||
for i := 0; i < 10; i++ { | ||
assert.Equal(t, i, s.PopV()) | ||
} | ||
}) | ||
} | ||
|
||
func randElems(n int) []int { | ||
// Deterministic element ordering | ||
r := rand.New(rand.NewSource(1)) | ||
|
||
var elems []int | ||
for i := 0; i < n; i++ { | ||
elems = append(elems, i) | ||
} | ||
r.Shuffle(len(elems), func(i, j int) { | ||
elems[i], elems[j] = elems[j], elems[i] | ||
}) | ||
return elems | ||
} |