gcs/gcs: use sort.Slice instead of sort.Sort, remove uint64Slice

This commit removes the uint64Slice type and performs sorting during
filter construction and ZipMatchAny using sort.Slice. The benchmarks
indicated that this speeds up BuildGCSFilter and ZipMatchAny by 10-12%,
likely to the overhead of needing to resolve the sort.Interface methods.

The benchmarks indicate that this improvement is not present for the
smallest query size in our benchmarks, i.e. 100 elements, but the
reduction is only about 3%. This would indicate the at these small
values, the use of reflection is actually slightly slower than interface
method resolution in total.
This commit is contained in:
Conner Fromknecht 2019-04-24 17:47:09 -07:00 committed by Olaoluwa Osuntokun
parent 8cea9a2e28
commit 9e5f4b9a99
2 changed files with 4 additions and 30 deletions

View file

@ -119,7 +119,7 @@ func BuildGCSFilter(P uint8, M uint64, key [KeySize]byte, data [][]byte) (*Filte
} }
// Build the filter. // Build the filter.
values := make(uint64Slice, 0, len(data)) values := make([]uint64, 0, len(data))
b := bstream.NewBStreamWriter(0) b := bstream.NewBStreamWriter(0)
// Insert the hash (fast-ranged over a space of N*P) of each data // Insert the hash (fast-ranged over a space of N*P) of each data
@ -138,7 +138,7 @@ func BuildGCSFilter(P uint8, M uint64, key [KeySize]byte, data [][]byte) (*Filte
v = fastReduction(v, nphi, nplo) v = fastReduction(v, nphi, nplo)
values = append(values, v) values = append(values, v)
} }
sort.Sort(values) sort.Slice(values, func(i, j int) bool { return values[i] < values[j] })
// Write the sorted list of values into the filter bitstream, // Write the sorted list of values into the filter bitstream,
// compressing it using Golomb coding. // compressing it using Golomb coding.
@ -374,7 +374,7 @@ func (f *Filter) ZipMatchAny(key [KeySize]byte, data [][]byte) (bool, error) {
b := bstream.NewBStreamReader(filterData) b := bstream.NewBStreamReader(filterData)
// Create an uncompressed filter of the search values. // Create an uncompressed filter of the search values.
values := make(uint64Slice, 0, len(data)) values := make([]uint64, 0, len(data))
// First, we cache the high and low bits of modulusNP for the // First, we cache the high and low bits of modulusNP for the
// multiplication of 2 64-bit integers into a 128-bit integer. // multiplication of 2 64-bit integers into a 128-bit integer.
@ -389,7 +389,7 @@ func (f *Filter) ZipMatchAny(key [KeySize]byte, data [][]byte) (bool, error) {
v = fastReduction(v, nphi, nplo) v = fastReduction(v, nphi, nplo)
values = append(values, v) values = append(values, v)
} }
sort.Sort(values) sort.Slice(values, func(i, j int) bool { return values[i] < values[j] })
querySize := len(values) querySize := len(values)

View file

@ -1,26 +0,0 @@
// Copyright (c) 2016-2017 The btcsuite developers
// Copyright (c) 2016-2017 The Lightning Network Developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package gcs
// uint64slice is a package-local utility class that allows us to use Go's sort
// package to sort a []uint64 by implementing sort.Interface.
type uint64Slice []uint64
// Len returns the length of the slice.
func (p uint64Slice) Len() int {
return len(p)
}
// Less returns true when the ith element is smaller than the jth element of
// the slice, and returns false otherwise.
func (p uint64Slice) Less(i, j int) bool {
return p[i] < p[j]
}
// Swap swaps two slice elements.
func (p uint64Slice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}