This change improves ComputeGeoRange() performance by avoiding trips
to the allocator by using pre-allocated byte slices. It also avoids
creation of interim byte slices by append()'ing directly to
returned output slices.
Parts of this change...
- before this change, ComputeGeoRange() would invoke relateAndRecurse(),
which would recursively invoke ComputeGeoRange(). Five of the
recursive call parameters... sminLon, sminLat, smaxLon, smaxLat,
and checkBoundaries... would be passed down on each invocation.
- in this change, ComputeGeoRange() was refactored to have two, internal
helper closures: relateAndRecurse() and computeGeoRange(), so that
those five parameters would be part of the closure and would no
longer need to be passed on each invocation.
- NewPrefixCodedInt64Prealloc() API was added to the numeric package
to allow the caller to optionally provide a pre-allocated byte slice.
- relatedAndRecurse() now uses this NewPrefixCodedInt64Prealloc() API,
via an internal helper closure function, makePrefixCoded().
- makePrefixCoded() manages a preallocated byte slice, where it
allocates another byte slice, as needed, which will be 2x the
size of its last preallocated slice.
- the previous relateAndRecurse() would return byte slices
of the terms that were on-the-boundary and not-on-the-boundary.
The caller, ComputeGeoRange(), would then append() those slices to
its own on-boundary/not-on-boundary slices, and then return those
onwards to its caller. All these interim slices, then, became garbage.
- In this commit, since relateAndRecurse() and computeGeoRange() are
now closures, they append() directly onto the final output
slices of the top-level ComputeGeoRange(), reducing garbage
and trips to the allocator.
Before the change...
BenchmarkComputeGeoRangePt01-8 100000 18516 ns/op 2005 B/op 63 allocs/op
BenchmarkComputeGeoRangePt1-8 10000 108882 ns/op 96267 B/op 736 allocs/op
BenchmarkComputeGeoRange10-8 50 35883331 ns/op 35812513 B/op 184543 allocs/op
BenchmarkComputeGeoRange100-8 10 192568538 ns/op 187524856 B/op 926510 allocs/op
After the change...
BenchmarkComputeGeoRangePt01-8 100000 12447 ns/op 280 B/op 7 allocs/op
BenchmarkComputeGeoRangePt1-8 30000 47053 ns/op 16416 B/op 28 allocs/op
BenchmarkComputeGeoRange10-8 100 11836988 ns/op 8503406 B/op 76 allocs/op
BenchmarkComputeGeoRange100-8 20 72555603 ns/op 42778777 B/op 89 allocs/op
See also: https://issues.couchbase.com/browse/MB-33455