aboutsummaryrefslogtreecommitdiff
path: root/src/sort
diff options
context:
space:
mode:
authorMartin Möhrmann <martisch@uos.de>2015-01-02 00:18:10 +0100
committerRobert Griesemer <gri@golang.org>2015-01-06 23:30:46 +0000
commite5864cd9397679353e44ab1de82fdf6d75a359c7 (patch)
tree11560a498af0fb4fbc6d910626a9bed4d3947141 /src/sort
parentbc2601a1df6efc089cbb2acd51bd181aeaba12c6 (diff)
downloadgo-e5864cd9397679353e44ab1de82fdf6d75a359c7.tar.gz
go-e5864cd9397679353e44ab1de82fdf6d75a359c7.zip
sort: optimize symMerge performance for blocks with one element
Use direct binary insertion instead of recursive calls to symMerge when one of the blocks has only one element. benchmark old ns/op new ns/op delta BenchmarkStableString1K 421999 397629 -5.77% BenchmarkStableInt1K 123422 120592 -2.29% BenchmarkStableInt64K 9629094 9620200 -0.09% BenchmarkStable1e2 123089 120209 -2.34% BenchmarkStable1e4 39505228 36870029 -6.67% BenchmarkStable1e6 8196612367 7630840157 -6.90% Change-Id: I49905a909e8595cfa05920ccf9aa00a8f3036110 Reviewed-on: https://go-review.googlesource.com/2219 Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/sort')
-rw-r--r--src/sort/sort.go48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/sort/sort.go b/src/sort/sort.go
index 600a486a0e..4ca027b614 100644
--- a/src/sort/sort.go
+++ b/src/sort/sort.go
@@ -359,6 +359,54 @@ func Stable(data Interface) {
// Having the caller check this condition eliminates many leaf recursion calls,
// which improves performance.
func symMerge(data Interface, a, m, b int) {
+ // Avoid unnecessary recursions of symMerge
+ // by direct insertion of data[a] into data[m:b]
+ // if data[a:m] only contains one element.
+ if m-a == 1 {
+ // Use binary search to find the lowest index i
+ // such that data[i] >= data[a] for m <= i < b.
+ // Exit the search loop with i == b in case no such index exists.
+ i := m
+ j := b
+ for i < j {
+ h := i + (j-i)/2
+ if data.Less(h, a) {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ // Swap values until data[a] reaches the position before i.
+ for k := a; k < i-1; k++ {
+ data.Swap(k, k+1)
+ }
+ return
+ }
+
+ // Avoid unnecessary recursions of symMerge
+ // by direct insertion of data[m] into data[a:m]
+ // if data[m:b] only contains one element.
+ if b-m == 1 {
+ // Use binary search to find the lowest index i
+ // such that data[i] > data[m] for a <= i < m.
+ // Exit the search loop with i == m in case no such index exists.
+ i := a
+ j := m
+ for i < j {
+ h := i + (j-i)/2
+ if !data.Less(m, h) {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ // Swap values until data[m] reaches the position i.
+ for k := m; k > i; k-- {
+ data.Swap(k, k-1)
+ }
+ return
+ }
+
mid := a + (b-a)/2
n := mid + m
var start, r int