Skip to content

Break out of the chaining lookback loop earlier - #646

Merged
marcelm merged 2 commits into
mainfrom
chaining-early-break
Oct 14, 2026
Merged

marcelm merged 2 commits into
mainfrom
chaining-early-break

Conversation

@ksahlin

@ksahlin ksahlin commented Sep 30, 2026

Copy link
Copy Markdown
Owner

collinear_chaining looks back at up to max_lookback previous anchors. It
stopped at an anchor on a different contig or, for collinear anchors
only, at an anchor at least max_ref_gap away. Because anchors are sorted
by reference start, all remaining anchors are then even further away and
cannot be chained. Both checks are now combined into a single comparison
of the reference start that is done first, for every anchor, so the loop
also stops early when it encounters non-collinear anchors. The same
bound is used when checking the best anchor so far.

In addition, the diagonal ratio test skips the division when both
distances are equal, in which case the ratio is exactly 1.

Output is unchanged. A new test compares the results with the previous
implementation on random anchors.

Speedup on an Apple M4 Max, -x, 1 thread, median of 5 runs:

  • maize, 10 kb reads: chaining -11%, total mapping time -4%
  • chrY, 10 kb reads: chaining -4%, total mapping time -3%
  • maize, 150 nt reads: chaining -7%, total mapping time -2%
  • chrY, 150 nt reads: chaining -4%, total mapping time unchanged
  • CHM13, 150 nt reads: chaining -3%, total mapping time unchanged
  • maize, 50 nt reads: chaining -2%, total mapping time -1%

collinear_chaining looks back at up to max_lookback previous anchors. It
stopped at an anchor on a different contig or, for collinear anchors
only, at an anchor at least max_ref_gap away. Because anchors are sorted
by reference start, all remaining anchors are then even further away and
cannot be chained. Both checks are now combined into a single comparison
of the reference start that is done first, for every anchor, so the loop
also stops early when it encounters non-collinear anchors. The same
bound is used when checking the best anchor so far.

@marcelm marcelm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are again two micro-optimizations in this PR:

  • min_ref_start
  • and avoiding computing the diagonal_ratio

I have split the single commit into two, one for each of the above optimizations, and benchmarked them separately. It seems both actually do give a small speedup. It is mostly invisible in the plots, but measurable when I do runtime measurements on a few selected libraries.

So while the speedup is small, the added code complexity is also small (I think the min_ref_start change is actually a bit more elegant than before), so let’s merge this.

I’ll push my changes shortly where I have split up the commit into two and added a changelog entry.

Comment thread src/chainer.rs Outdated
}

#[test]
fn collinear_chaining_matches_reference() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think writing such a test is a great way to convince oneself during development that the modified function gives the same results as the original, but IMO it should then be deleted afterwards. Otherwise, we would just be adding more and more versions of this function, and it would become a nightmare to maintain as soon as the chainer actually does change behavior intentionally. Additionally, we already test that our results don’t change (the baseline comparisons).

The division can be skipped when both distances are equal,
in which case the ratio is 1.
@marcelm
marcelm force-pushed the chaining-early-break branch from fbfa392 to 9270387 Compare October 14, 2026 08:41
@marcelm
marcelm merged commit 49211a7 into main Oct 14, 2026
7 checks passed
@marcelm
marcelm deleted the chaining-early-break branch October 14, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants