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:
parent
17aa010ebf
commit
ebbcd71b3d
@ -129,13 +129,14 @@ func numbersHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// sort fallthrough, either the inputChan is currently "empty"
|
// sort fallthrough, either the inputChan is currently "empty"
|
||||||
// or we fetched all URLs already
|
// or we fetched all URLs already
|
||||||
go func(n []int) {
|
go func(sorted []int, unsorted_buffer []int) {
|
||||||
res, err := sort.SortedAndDedup(ctx, n)
|
res, err := sort.SortedAndDedup(ctx, unsorted_buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sortChan <- res
|
merged := sort.MergeLists(sortedNumbers, res)
|
||||||
}(append(sortedNumbers, numberBuffer...))
|
sortChan <- merged
|
||||||
|
}(sortedNumbers, numberBuffer)
|
||||||
numberBuffer = []int{}
|
numberBuffer = []int{}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -6,6 +6,39 @@ import (
|
|||||||
"fmt"
|
"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.
|
// Mergesorts and deduplicates the list.
|
||||||
func SortedAndDedup(ctx context.Context, list []int) (res []int, err error) {
|
func SortedAndDedup(ctx context.Context, list []int) (res []int, err error) {
|
||||||
sorted, err := Mergesort(ctx, list)
|
sorted, err := Mergesort(ctx, list)
|
||||||
|
@ -5,6 +5,40 @@ import (
|
|||||||
"testing"
|
"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.
|
// Test the mergesort and deduplication with a predefined set of slices.
|
||||||
func TestSortAndDedup(t *testing.T) {
|
func TestSortAndDedup(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
Loading…
Reference in New Issue
Block a user