Skip to content

perf(group): encode each UMI once in the sequential assigners - #623

Merged
nh13 merged 1 commit into
mainfrom
nh/assigner-encode-once
Jul 23, 2026
Merged

nh13 merged 1 commit into
mainfrom
nh/assigner-encode-once

Conversation

@nh13

@nh13 nh13 commented Jul 21, 2026 •

Copy link
Copy Markdown
Member

Summary

Each sequential UMI assigner (edit, adjacency, paired) re-ran BitEnc::from_umi_str several times per UMI and threw the result away, keeping only .len() or .is_some(). The differing-length guard added in #510 compounded this on the paired path: underlying_umi_len (which splits the prefixed key and encodes both halves) was called up to three times per UMI — in the encodability filter, the length guard, and the per-record strand resolution in the single-molecule fast path.

This encodes each UMI once and reuses the result everywhere:

assigner from_umi_str calls per UMI, before → after
edit 2 → 1
adjacency 2 → 1
paired 6 → 2 (one underlying_umi_len)

BitEnc is a 16-byte Copy struct, so the cached Vec<Option<BitEnc>> (paired: a Vec<Option<usize>> of underlying base lengths) is far cheaper than repeating the per-byte encode.

Correctness

Behaviour-preserving by construction — every cached value is a pure function of a string that does not change between the cache write and its reads.

  • count_paired now carries the underlying base length. This is sound because canonicalization only ever swaps the two halves (A-B ↔ B-A), which leaves the base multiset — and therefore both BitEnc-encodability and the summed base count — unchanged, so every raw UMI folding into a canonical form contributes the same value.
  • assign_with_invalid_fallback's resolve closure now receives the UMI's position so callers can index the precomputed encoding.
  • The GRP-01 cross-assigner parity guarantees from fix(group): reject UMIs of differing length in all assigners (GRP-01) #510 are untouched: test_sequential_and_parallel_assigners_induce_same_partition passes unchanged.
  • Added two tests pinning the carried-length invariant (valid folding, and an N-containing UMI staying None through canonicalization).

Full workspace suite: 5589 passed, 23 skipped. cargo ci-fmt / ci-lint clean.

Performance

Measured on a c7g.4xlarge (Graviton3, matching the benchmark fleet), --threads 0, GNU time -v user CPU, 3 reps, with the untouched identity strategy as a control:

sample strategy base this PR Δ
agilent-hs2 paired 93.35s 92.39s −1.0%
agilent-hs2 identity (control) 85.30s 85.66s +0.4%

Complete rep separation on paired (every base rep slower than every branch rep). Family-size histograms and molecule counts are byte-identical before/after (paired 10,220,662; identity 10,292,162).

Scope

This removes the redundant computation on the sequential paths. Profiling attributes the larger share of the paired path's recent cost to per-UMI allocations (reverse() building a fresh String on every adjacency comparison; canonicalize_paired; the already-uppercase input still being re-allocated). Those are a separate, self-contained follow-up and are intentionally not bundled here.

Summary by CodeRabbit

  • Bug Fixes
    • Improved consistency of UMI assignment between sequential and parallel workflows.
    • Invalid or non-encodable UMIs are now handled consistently across simple, adjacency-based, and paired assignment paths, including correct length validation and molecule-ID mapping.
    • Paired-UMI processing now preserves invalid/unknown underlying states (None) through canonicalization and grouping, ensuring invalid paired UMIs remain isolated.
  • Tests
    • Extended test coverage for paired-Umi None propagation and isolation of invalid inputs.

@nh13
nh13 temporarily deployed to github-actions July 21, 2026 09:09 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9b335bc6-d89c-4253-99b0-102939a6e9d5

📥 Commits

Reviewing files that changed from the base of the PR and between 7dde8dc and 70f2a73.

📒 Files selected for processing (1)
  • crates/fgumi-umi/src/assigner.rs

Walkthrough

Invalid UMIs are encoded once and tracked through validation, matching, canonicalization, and molecule-ID mapping. Simple, adjacency, and paired assigners now apply consistent cached-validity rules.

Changes

UMI assignment consistency

Layer / File(s) Summary
Fallback and single-UMI assignment
crates/fgumi-umi/src/assigner.rs
The fallback resolver receives the input index; simple assignment caches BitEnc results, excludes invalid UMIs from clustering and length checks, and reuses cached values for final mapping.
Adjacency assignment
crates/fgumi-umi/src/assigner.rs
Adjacency inputs accept carried encodability metadata, while assignment reuses cached encodings across counting, validation, fast-path selection, and mapping.
Paired assignment and validation
crates/fgumi-umi/src/assigner.rs
Paired counting carries underlying validity through canonicalization, assignment filters and validates using cached values, and tests cover invalid reverse-oriented spellings and isolation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: fgumi runall

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: caching per-UMI encodings in the sequential assigners.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nh/assigner-encode-once

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.68421% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.54%. Comparing base (4bd2824) to head (70f2a73).
⚠️ Report is 17 commits behind head on main.

Files with missing lines Patch % Lines
crates/fgumi-umi/src/assigner.rs 98.68% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #623      +/-   ##
==========================================
+ Coverage   93.52%   93.54%   +0.02%     
==========================================
  Files         175      175              
  Lines      105404   106015     +611     
==========================================
+ Hits        98574    99170     +596     
- Misses       6830     6845      +15     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/fgumi-umi/src/assigner.rs`:
- Around line 2719-2763: Extend the paired-UMI regression test around
PairedUmiAssigner::count_paired to verify the assignment outcome after invalid
entries with None underlying lengths are filtered, not only the carried lengths.
Add the generated fgbio identity baseline or explicitly assert the documented
invalid-UMI divergence, while preserving the existing canonicalization and
length assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a0fa7da4-7615-4d9d-861f-79fd337e2b74

📥 Commits

Reviewing files that changed from the base of the PR and between 4bd2824 and 7dde8dc.

📒 Files selected for processing (1)
  • crates/fgumi-umi/src/assigner.rs

Comment thread crates/fgumi-umi/src/assigner.rs
The sequential edit, adjacency, and paired assigners each re-ran
BitEnc::from_umi_str several times per UMI and discarded the result,
keeping only .len() or .is_some(). On the paired path this compounded:
the differing-length guard added in #510 called underlying_umi_len (which
encodes both halves of the prefixed key) up to three times per UMI -- in
the encodability filter, the length guard, and the per-record strand
resolution in the single-molecule fast path.

Encode each UMI once into a Vec<Option<BitEnc>> (paired: a Vec of
underlying base lengths) and reuse it for all three sites. BitEnc is a
16-byte Copy struct, so caching it is far cheaper than repeating the
per-byte encode. count_paired now carries the underlying length; this is
sound because canonicalization only swaps the two halves (A-B <-> B-A),
which preserves both BitEnc-encodability and the summed base count, so
every raw UMI folding into a canonical form contributes the same value.

Grouping output is unchanged: family-size histograms and molecule counts
are byte-identical before and after. On a c7g.4xlarge at threads=0 this
recovers ~1% of paired group runtime on agilent-hs2 (93.4s -> 92.4s user),
with the untouched identity strategy flat as a control.

Encode calls per UMI: edit 2->1, adjacency 2->1, paired 6->2.
@nh13
nh13 force-pushed the nh/assigner-encode-once branch from 7dde8dc to 70f2a73 Compare July 23, 2026 05:22
@nh13
nh13 temporarily deployed to github-actions July 23, 2026 05:23 — with GitHub Actions Inactive
@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13
nh13 merged commit fb5a104 into main Jul 23, 2026
14 checks passed
@nh13
nh13 deleted the nh/assigner-encode-once branch July 23, 2026 08:50
@nh13 nh13 mentioned this pull request Jul 23, 2026

This branch was previously deployed

1 inactive deployment
github-actions — 70f2a734 Deployed Jul 23, 2026 by nh13 via coverage #2935
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.

1 participant