Skip to content

Commit aee0221

Browse files
qsort: add benchmarks from the standard library
These will let us be more confident that a custom sort algorithm makes sense to use, especially when e.g. the Go standard library introduces a new sorting algorithm, we can compare the two. On my Mac, using the pdqsort from Go 1.19, the relevant timings are: Sort8/100000-10 4.91ms ± 0% Sort8/1000000-10 60.1ms ± 0% StdlibSort8/100000-10 8.16ms ± 0% StdlibSort8/1000000-10 103ms ± 0% Sort8/100000-10 163MB/s ± 0% Sort8/1000000-10 133MB/s ± 0% StdlibSort8/100000-10 98.0MB/s ± 0% StdlibSort8/1000000-10 77.5MB/s ± 0% Compared to the Go 1.18 sort algorithm: Sort8/100000-10 4.90ms ± 0% Sort8/1000000-10 59.0ms ± 0% StdlibSort8/100000-10 8.53ms ± 0% StdlibSort8/1000000-10 105ms ± 0% Sort8/100000-10 163MB/s ± 0% Sort8/1000000-10 136MB/s ± 0% StdlibSort8/100000-10 93.8MB/s ± 0% StdlibSort8/1000000-10 76.0MB/s ± 0% So the Go standard library sort performance is improving but we are still about 40% faster than the benchmark.
1 parent 3e23660 commit aee0221

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

qsort/sort_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111

1212
var prng = rand.New(rand.NewSource(0))
1313

14+
// Note, "8", "16", "32" etc are all byte measurements, not bits. So a 32 byte
15+
// integer, for example, which you might see in e.g. a SHA256 hash.
16+
1417
func TestSort8(t *testing.T) {
1518
testSort(t, 8)
1619
}
@@ -162,6 +165,31 @@ func BenchmarkSort8(b *testing.B) {
162165
}
163166
}
164167

168+
func stdlibSort8(b *testing.B, size int) {
169+
// 8 bytes per int64
170+
b.SetBytes(8 * int64(size))
171+
data := make([]int64, size)
172+
unsorted := make([]int64, size)
173+
for j := 0; j < len(unsorted); j++ {
174+
unsorted[j] = int64(rand.Intn(size / 10))
175+
}
176+
b.StopTimer()
177+
for i := 0; i < b.N; i++ {
178+
copy(data, unsorted)
179+
b.StartTimer()
180+
sort.Slice(data, func(i, j int) bool { return data[i] < data[j] })
181+
b.StopTimer()
182+
}
183+
}
184+
185+
func BenchmarkStdlibSort8(b *testing.B) {
186+
for _, size := range []int{1e5, 1e6} {
187+
b.Run(strconv.Itoa(size), func(b *testing.B) {
188+
stdlibSort8(b, size)
189+
})
190+
}
191+
}
192+
165193
func BenchmarkSort8Indirect(b *testing.B) {
166194
swap := func(int, int) {}
167195
const count = 100000
@@ -222,6 +250,7 @@ const (
222250

223251
func benchSort(count, size int, order order, indirect func(int, int)) func(*testing.B) {
224252
return func(b *testing.B) {
253+
b.StopTimer()
225254
buf := make([]byte, count*size)
226255
unsorted := make([]byte, count*size)
227256
prng.Read(unsorted)
@@ -238,11 +267,12 @@ func benchSort(count, size int, order order, indirect func(int, int)) func(*test
238267
}
239268

240269
b.SetBytes(int64(len(buf)))
241-
b.ResetTimer()
242270

243271
for i := 0; i < b.N; i++ {
244272
copy(buf, unsorted)
273+
b.StartTimer()
245274
Sort(buf, size, indirect)
275+
b.StopTimer()
246276
}
247277
}
248278
}

0 commit comments

Comments
 (0)