Skip to content

perf(tags): cache UMI position in DecodedRecord to avoid per-record duplicate find_tag_position scan #334

Closed

Description

@nh13

fgumi_raw_bam::tags::find_tag_position accounts for ~5% of CPU time on fgumi group (4.94% measured on a CODEC 8M-record samply profile, threads=4). The function itself is well-optimized (u16 tag compare, early-exit on missing length sentinels), and the existing single-pass extractors (extract_aux_string_tags, extract_template_aux_tags, filter_template_raw's inline loop) already amortize multi-tag lookups within a single function call.

The remaining cost is structural: the same record's aux data is scanned multiple times across the chain because each step looks up tags independently:

Site Tags looked up
compute_group_key_from_raw (bam.rs:448) — Decode RG, CB, MC (single-pass via extract_aux_string_tags)
filter_template_raw (group.rs:170-233) — Process MQ, RX (single-pass inline loop)
assign_umi_groups_for_indices_impl (group.rs:467) — Process RX (separate find_string_tag call)
update_string_tag via emit_templates_raw_with_mi (group.rs:2057) — Serialize MI (read-modify-write)

For an 8M-record fgumi group run that's ~3 separate aux-data scans per record on top of the single-pass extractors. RX in particular is scanned twice (once during filter, once during UMI assignment).

Proposed fix. Add umi_offset: u32 and umi_len: u16 to DecodedRecord (or the equivalent intermediate carrier), populated once in the Decode step alongside the GroupKey. Downstream assign_umi_groups_* reads the UMI bytes by slice into the cached offset/len without a second find_tag_position call. Estimated saving: ≈100 samples on fgumi group-like workloads.

Verification approach. Profile-diff target/profiling/fgumi group with samply at 999 Hz before/after on agilent-hs2.mapped.bam (53M records); expect find_tag_position (and its callers in assign_umi_groups_for_indices_impl) to drop by roughly half their current contribution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions