1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:08:32 -06:00

sort: reduce leaf calls in Stable

Move the symMerge recursion stopping condition
from the beginning of symMerge to the callers.

This halves the number of calls to symMerge
while running 'go test sort'.

benchmark                   old ns/op      new ns/op      delta
BenchmarkStable1e6          8358117060     7954143849     -4.83%
BenchmarkStable1e4          40116117       38583285       -3.82%
BenchmarkStableInt1K        119150         115182         -3.33%
BenchmarkStableInt64K       9799845        9515475        -2.90%
BenchmarkStableString1K     388901         393516         +1.19%
BenchmarkStable1e2          124917         123618         -1.04%

Change-Id: I7ba2ca277f213b076fe6830e1139edb47ac53800
Reviewed-on: https://go-review.googlesource.com/1820
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2014-12-18 13:11:08 -08:00
parent a48e789635
commit 2a617d46f3

View File

@ -316,7 +316,7 @@ func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
// data.Less and O(n*log(n)*log(n)) calls to data.Swap.
func Stable(data Interface) {
n := data.Len()
blockSize := 20
blockSize := 20 // must be > 0
a, b := 0, blockSize
for b <= n {
insertionSort(data, a, b)
@ -332,7 +332,9 @@ func Stable(data Interface) {
a = b
b += 2 * blockSize
}
symMerge(data, a, a+blockSize, n)
if m := a + blockSize; m < n {
symMerge(data, a, m, n)
}
blockSize *= 2
}
}
@ -352,11 +354,11 @@ func Stable(data Interface) {
// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
// in the paper carries through for Swap operations, especially as the block
// swapping rotate uses only O(M+N) Swaps.
//
// symMerge assumes non-degenerate arguments: a < m && m < b.
// Having the caller check this condition eliminates many leaf recursion calls,
// which improves performance.
func symMerge(data Interface, a, m, b int) {
if a >= m || m >= b {
return
}
mid := a + (b-a)/2
n := mid + m
var start, r int
@ -380,8 +382,12 @@ func symMerge(data Interface, a, m, b int) {
end := n - start
rotate(data, start, m, end)
symMerge(data, a, start, mid)
symMerge(data, mid, end, b)
if a < start && start < mid {
symMerge(data, a, start, mid)
}
if mid < end && end < b {
symMerge(data, mid, end, b)
}
}
// Rotate two consecutives blocks u = data[a:m] and v = data[m:b] in data: