It is already in the standard library
The last step ended on a question: why does insertion sort beat sort.Slice on
nearly-sorted data up to about 2,000, and lose after that?
The answer is not in your code. It is in Go's standard library.
Inside sort.Slice
sort.Slice calls pdqsort, a quicksort variant you will meet next lesson. But
its very first decision is this:
// src/sort/zsortfunc.go
const maxInsertion = 12
for {
length := b - a
if length <= maxInsertion {
insertionSort_func(data, a, b)
return
}
...
}
When a range shrinks to twelve elements or fewer, pdqsort stops dividing
and calls insertion sort.
Not as a fallback. As the ordinary, most-frequently-executed path: an algorithm that halves the array spends most of its time on small ranges.
sort.SliceStable is even more direct
// src/sort/zsortfunc.go
func stable_func(data lessSwap, n int) {
blockSize := 20
a, b := 0, blockSize
for b <= n {
insertionSort_func(data, a, b)
a = b
b += blockSize
}
...
}
The standard library's stable sort begins by insertion-sorting every 20-element block, and only then merges them.
And there is a third place — partialInsertionSort_func, called under the
comment "The slice is likely already sorted". That is the same shortcut you
just measured in your own code.
So why does sort.Slice win at n = 10,000?
Not because it avoids insertion sort. Because it uses it only where it is good — on small ranges — and applies a dividing strategy you have not learned yet to the large array first.
It is not an alternative to insertion sort. It is insertion sort plus something else, and that something else is the next lesson.
The conclusion worth keeping
Elementary sorts are not defeated technology. They are components. They lose as a standalone answer on large data, and they win where the data is small or nearly ordered — and those cases make up most of the work inside any serious sort.
Bubble sort plays no part in this story. It is not inside anything, and its only home is this lesson: it shows you what O(n²) looks like when nothing softens it.
The figures in this step come from the Go 1.26.4 source on this machine
(src/sort/zsortfunc.go), not from documentation and not from memory.
maxInsertion = 12 and blockSize = 20 are that version's constants; another Go
release may differ. Check for yourself — the source ships with your Go install.