Go Benchmark
sort.Slice vs slices.Sort
The old sort package against the generic slices package — same algorithm, different dispatch.
Go now ships four ways to sort a slice: the classic sort.Sort with a hand-written sort.Interface, the closure-based sort.Slice, and the generic slices.Sort and slices.SortFunc added in Go 1.21. They use closely related pattern-defeating quicksort algorithms, so the interesting difference is dispatch: interface method calls and closures cannot be fully inlined and box their data, while the generic functions are compiled for the concrete element type. This benchmark sorts the same shuffled 1000-element int slice with each API. If you are still reaching for sort.Slice out of habit, the chart shows what switching to slices.Sort buys.
1 CPU
32 CPUs
slices.Sort(work) — the generic sort for ordered element types. Comparisons compile down to plain < on the concrete type with no function calls at all, which is why it is consistently the fastest way to sort a slice in Go.
Slices Sort Func #
slices.SortFunc(work, cmp) — the generic replacement for sort.Slice. The slice is accessed directly at its concrete type (no reflection, no boxing), but every comparison still goes through the provided function, which limits inlining.
Sort Interface #
sort.Sort(IntSlice(work)) with a hand-written Len/Less/Swap implementation. Avoids reflection, but every single comparison and swap is an interface method call — the dispatch cost the generic APIs were designed to eliminate.
sort.Slice(work, func(i, j int) bool { ... }) — the pre-generics convenience API. Internally it uses reflection (reflect.Swapper) for swapping elements and calls the comparison closure through a function pointer, both of which add per-element overhead the compiler cannot optimize away.
Contributors