-
Notifications
You must be signed in to change notification settings - Fork 0
/
sort_test.go
127 lines (105 loc) · 3.51 KB
/
sort_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package sort_test
import (
"testing"
fastsort "github.com/jordan-bonecutter/sort"
"math/rand"
"runtime"
"sort"
"time"
)
const InputSize = 10000
const BenchIters = 1000
func NewRandArray[T any](length int, rvg func() T) []T {
ret := make([]T, length)
for idx := 0; idx < length; idx++ {
ret[idx] = rvg()
}
return ret
}
func TestSortCapability(t *testing.T) {
data := NewRandArray(InputSize, rand.Int)
fastsort.Ordered(data)
if !sort.IntsAreSorted(data) {
t.Errorf("Failed sorting array!")
}
}
func TestSortSpeed(t *testing.T) {
avgFastSorterDur := getAvgSpeed[int](fastsort.Ordered[int], rand.Int)
t.Logf("Fast implementation took %v", avgFastSorterDur)
avgFastLessSorterDur := getAvgSpeed[int](func(data []int) {
fastsort.LessSort[int](data, func(a, b *int) bool { return *a < *b })
}, rand.Int)
t.Logf("Fast LessSort implementation took %v", avgFastLessSorterDur)
avgDefaultSorterDur := getAvgSpeed[int](sort.Ints, rand.Int)
t.Logf("Default implementation took %v", avgDefaultSorterDur)
if avgFastSorterDur >= avgDefaultSorterDur {
t.Errorf("Default implementation(%v) should be slower than generic implementation(%v).", avgDefaultSorterDur, avgFastSorterDur)
}
if avgFastSorterDur >= avgFastLessSorterDur {
t.Errorf("Ordered implementation(%v) should be faster than less implementation(%v).", avgFastSorterDur, avgFastLessSorterDur)
}
}
func getAvgSpeed[T any](sorter func([]T), rvg func() T) time.Duration {
var total time.Duration
for iter := 0; iter < BenchIters; iter++ {
data := NewRandArray(InputSize, rvg)
runtime.GC()
start := time.Now()
sorter(data)
end := time.Now()
total += end.Sub(start)
}
return total / BenchIters
}
type Person struct {
Name string
Age int
}
func Younger(a, b *Person) bool {
return a.Age < b.Age
}
func RandomPerson() Person {
return Person{ Age: rand.Int() }
}
func TestSortLessCapability(t *testing.T) {
data := NewRandArray(InputSize, RandomPerson)
fastsort.LessSort(data, Younger)
if !sort.SliceIsSorted(data, func(i, j int) bool {
return Younger(&data[i], &data[j])
}) {
t.Errorf("Failed sorting array!")
}
}
func TestLessSortSpeed(t *testing.T) {
avgFastSorterDur := getAvgSpeed[Person](func(data []Person) {
fastsort.LessSort(data, Younger)
}, RandomPerson)
t.Logf("Less sort implementation took %v", avgFastSorterDur)
avgFieldSorterDur := getAvgSpeed[Person](func(data []Person) {
proto := Person{}
fastsort.StructField[Person, int](&proto, &proto.Age, data)
}, RandomPerson)
t.Logf("Struct field implementation took %v", avgFieldSorterDur)
avgDefaultSorterDur := getAvgSpeed[Person](func(data []Person) {
sort.Slice(data, func(i, j int) bool {
return Younger(&data[i], &data[j])
})
}, RandomPerson)
t.Logf("Default implementation took %v", avgDefaultSorterDur)
if avgFastSorterDur >= avgDefaultSorterDur {
t.Errorf("Default implementation(%v) should be slower than generic implementation(%v).", avgDefaultSorterDur, avgFastSorterDur)
}
if avgFieldSorterDur >= avgFastSorterDur {
t.Errorf("Less function implementation(%v) should be slower than struct field implementation(%v).", avgFastSorterDur, avgFieldSorterDur)
}
}
func TestFieldSortCorrectness(t *testing.T) {
data := NewRandArray(InputSize, RandomPerson)
proto := Person{}
fastsort.StructField[Person, int](&proto, &proto.Age, data)
if !sort.SliceIsSorted(data, func(i, j int) bool {
return Younger(&data[i], &data[j])
}) {
t.Errorf("Failed sorting array!")
}
}