Skip to content

Commit

Permalink
fix performance issue on AllIntersections
Browse files Browse the repository at this point in the history
This commit addresses a performance issue in the AllIntersections
function, where the conditional for traversing the right side of the
tree was evaluating to true most of the time. This led to unnecessary
visits of right nodes, resulting in linear time complexity.

More background on why this fix is correct:

- Left is safe to prune when all lower nodes end before the start of the
  lookup interval (`Left.MaxEnd < start`). (Note: this case was already
  correct before this commit, but I reversed the inequality as I find it
  easier to reason about)
- Right is safe to prune when all higher nodes start after the end of
  lookup interval (`end < Current.Start`). If the current node starts
  after the end of the lookup interval, we're guaranteed all its right
  nodes will also because they all start after the current node by
  definition.

Fuzz testing yielded consistent results with original implementation.
Benchmark showed ~30% speed improvement on average case (random
intervals), and over 99.9% improvement in worst case (lookup interval at
the far left of the tree). As expected, new implementation explores
fewer nodes that can be evicted just as safely in advance.
  • Loading branch information
gilbsgilbs authored and rdleal committed Dec 16, 2024
1 parent 93fac80 commit 178e917
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions interval/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ func (st *SearchTree[V, T]) AllIntersections(start, end T) ([]V, bool) {
}

func searchInOrder[V, T any](n *node[V, T], start, end T, cmp CmpFunc[T], foundFn func(interval[V, T])) {
if n.Left != nil && cmp.gte(n.Left.MaxEnd, start) {
if n.Left != nil && cmp.lte(start, n.Left.MaxEnd) {
searchInOrder(n.Left, start, end, cmp, foundFn)
}

if n.Interval.intersects(start, end, cmp) {
foundFn(n.Interval)
}

if n.Right != nil && cmp.gte(n.Right.MaxEnd, start) {
if n.Right != nil && cmp.lte(n.Interval.Start, end) {
searchInOrder(n.Right, start, end, cmp, foundFn)
}
}
Expand Down

0 comments on commit 178e917

Please sign in to comment.