slices
are no longer experimental, so the question is very much valid for the current Go. I've tried the following:
import (
"cmp"
"math/rand/v2"
"slices"
"sort"
"testing"
)
const (
seed1 = 42
seed2 = 100_500
numElements = 100_000
)
func BenchmarkSortInts(b *testing.B) {
var (
random = rand.New(rand.NewPCG(seed1, seed2)) // static seeds for reproducible results
arr = random.Perm(numElements)
arrcp = slices.Clone(arr)
)
b.Run("sort.Ints", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
sort.Ints(arrcp)
}
})
b.Run("sort.Sort", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
sort.Sort(sort.IntSlice(arrcp))
}
})
b.Run("sort.Slice", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
sort.Slice(arrcp, func(i, j int) bool {
return arrcp[i] < arrcp[j]
})
}
})
b.Run("slices.Sort", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
slices.Sort(arrcp)
}
})
b.Run("slices.SortFunc", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
slices.SortFunc(arrcp, cmp.Compare)
}
})
b.Run("slices.SortCustomFunc", func(b *testing.B) {
for range b.N {
b.StopTimer()
copy(arrcp, arr)
b.StartTimer()
slices.SortFunc(arrcp, func(a, b int) int { return a - b })
}
})
}
And it gave me these results (Go 1.23, averaged over 10 runs):
goos: linux
goarch: amd64
pkg: github.com/nspcc-dev/neo-go/config
cpu: AMD Ryzen 7 PRO 7840U w/ Radeon 780M Graphics
│ sorting │
│ sec/op │
SortInts/sort.Ints-16 4.365m ± 1%
SortInts/sort.Sort-16 7.895m ± 1%
SortInts/sort.Slice-16 7.648m ± 1%
SortInts/slices.Sort-16 4.380m ± 1%
SortInts/slices.SortFunc-16 6.846m ± 0%
SortInts/slices.SortCustomFunc-16 6.248m ± 1%
geomean 6.057m
│ sorting │
│ B/op │
SortInts/sort.Ints-16 0.000 ± 0%
SortInts/sort.Sort-16 24.00 ± 0%
SortInts/sort.Slice-16 56.00 ± 0%
SortInts/slices.Sort-16 0.000 ± 0%
SortInts/slices.SortFunc-16 0.000 ± 0%
SortInts/slices.SortCustomFunc-16 0.000 ± 0%
geomean ¹
¹ summaries must be >0 to compute geomean
│ sorting │
│ allocs/op │
SortInts/sort.Ints-16 0.000 ± 0%
SortInts/sort.Sort-16 1.000 ± 0%
SortInts/sort.Slice-16 2.000 ± 0%
SortInts/slices.Sort-16 0.000 ± 0%
SortInts/slices.SortFunc-16 0.000 ± 0%
SortInts/slices.SortCustomFunc-16 0.000 ± 0%
geomean ¹
¹ summaries must be >0 to compute geomean
sort.Ints
in fact just calls slices.Sort
now (1.22+) internally (see https://pkg.go.dev/sort#Ints) and the result just proves it. All the other ways incur noticeably more overhead. So in general slices.Sort
works fine when it can be used and likely slices
are also a bit better now in more complex scenarios like How to sort struct with multiple sort parameters?.