Skip to content

Instantly share code, notes, and snippets.

@Merovius
Created January 29, 2023 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Merovius/f52974941d81b17320d45969d1a27594 to your computer and use it in GitHub Desktop.
Save Merovius/f52974941d81b17320d45969d1a27594 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/base64"
"math/rand"
"testing"
"x/esort"
"golang.org/x/exp/constraints"
"golang.org/x/exp/slices"
)
type Person struct {
GivenName string
ID int
}
type LessFn[T any] func(l, r T) bool
func (f LessFn[T]) Reverse(l, r T) bool {
return f(r, l)
}
type Chain[T any] []LessFn[T]
func (c Chain[T]) Less(l, r T) bool {
for _, f := range c {
switch {
case f(l, r):
return true
case f(r, l):
return false
}
}
return false
}
func Less[T constraints.Ordered](l, r T) bool {
return l < r
}
func By[C any, F constraints.Ordered](by func(C) F) LessFn[C] {
return func(l, r C) bool { return Less(by(l), by(r)) }
}
func ByFunc[C, F any](by func(C) F, less func(F, F) bool) LessFn[C] {
return func(l, r C) bool { return less(by(l), by(r)) }
}
func genPeople(r *rand.Rand, n int) []Person {
p := make([]Person, n)
for i := range p {
buf := make([]byte, r.Intn(5))
r.Read(buf)
p[i].GivenName = base64.RawURLEncoding.EncodeToString(buf)
p[i].ID = r.Intn(n)
}
return p
}
const N = 1000000
func benchSorter(b *testing.B, sort func([]Person)) {
r := rand.New(rand.NewSource(0))
p := genPeople(r, N)
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
r.Shuffle(N, func(i, j int) { p[i], p[j] = p[j], p[i] })
b.StartTimer()
sort(p)
}
}
func BenchmarkMy(b *testing.B) {
benchSorter(b, func(p []Person) {
cmp := Chain[Person]{
By(func(p Person) string { return p.GivenName }).Reverse,
By(func(p Person) int { return p.ID }),
}
slices.SortFunc(p, cmp.Less)
})
}
func BenchmarkMatt(b *testing.B) {
benchSorter(b, func(p []Person) {
sorter := new(esort.Sorter[Person]).
ByString(func(p Person) string { return p.GivenName }, esort.Desc).
ByInt(func(p Person) int { return p.ID }, esort.Asc)
slices.SortFunc(p, sorter.Less)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment