Optimize merging/sorting

Previously we sorted a list e.g. [3,2,1]
that we already got, then fetched another
list e.g. [6,7,8,2]. Instead of just
sorting the new list and manually merging it
we would sort the appended lists:
[1,2,3,  6,7,8,2]

Despite mergesort, this is now optimized in
a two-step process:
* ONLY sort the new list
* call a Merge function on both lists, that assumes
  sorted and deduplicated lists

This should be faster.
This commit is contained in:
Julian Ospald 2017-09-11 13:15:43 +02:00
parent 17aa010ebf
commit ebbcd71b3d
3 changed files with 72 additions and 4 deletions

View File

@ -129,13 +129,14 @@ func numbersHandler(w http.ResponseWriter, r *http.Request) {
// sort fallthrough, either the inputChan is currently "empty"
// or we fetched all URLs already
go func(n []int) {
res, err := sort.SortedAndDedup(ctx, n)
go func(sorted []int, unsorted_buffer []int) {
res, err := sort.SortedAndDedup(ctx, unsorted_buffer)
if err != nil {
return
}
sortChan <- res
}(append(sortedNumbers, numberBuffer...))
merged := sort.MergeLists(sortedNumbers, res)
sortChan <- merged
}(sortedNumbers, numberBuffer)
numberBuffer = []int{}
select {

View File

@ -6,6 +6,39 @@ import (
"fmt"
)
// Merge too already sorted and deduplicated lists.
func MergeLists(l []int, r []int) []int {
n := []int{}
i := 0
j := 0
for {
if i == len(l) && j == len(r) {
break
} else if i == len(l) {
n = append(n, r[j:]...)
break
} else if j == len(r) {
n = append(n, l[i:]...)
break
}
if l[i] < r[j] {
n = append(n, l[i])
i++
} else if l[i] > r[j] {
n = append(n, r[j])
j++
} else if l[i] == r[j] {
n = append(n, l[i])
i++
j++
}
}
return n
}
// Mergesorts and deduplicates the list.
func SortedAndDedup(ctx context.Context, list []int) (res []int, err error) {
sorted, err := Mergesort(ctx, list)

View File

@ -5,6 +5,40 @@ import (
"testing"
)
func TestMergeLists(t *testing.T) {
ls := [][]int{
{1, 3, 4, 5, 7},
{1, 3, 4, 5, 7},
{},
{1, 3, 4, 5, 7},
{},
}
rs := [][]int{
{3, 4, 6, 9},
{},
{1, 3, 4, 5, 7},
{3, 5, 7},
{},
}
result := [][]int{
{1, 3, 4, 5, 6, 7, 9},
{1, 3, 4, 5, 7},
{1, 3, 4, 5, 7},
{1, 3, 4, 5, 7},
{},
}
for i := range ls {
merge := MergeLists(ls[i], rs[i])
if slice_equal(merge, result[i]) != true {
t.Errorf("Failure in merging, expected %s got %s", result[i], merge)
}
}
}
// Test the mergesort and deduplication with a predefined set of slices.
func TestSortAndDedup(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())