Performance
The pileup engine is the innermost loop of Rastair's processing pipeline: for a typical 30× whole-genome BAM, it processes ~3 billion reference positions, each with ~30 aligned reads. These rules specify performance-sensitive behaviors to avoid unnecessary overhead in this hot path.
Sources: Seqair-specific performance rules with no upstream spec counterpart. Implementation strategies are guided by profiling results and cross-checked against [htslib] behaviour. See References.
Allocation avoidance
The pileup engine allocates a Vec<PileupAlignment> per column using Vec::with_capacity(active.len()). Reusing a buffer via clone was measured to be slower than fresh allocation due to the copy cost of entries. The allocator efficiently reuses recently-freed blocks of the same size.
When a record enters the pileup active set, the engine MUST retrieve the record data once and cache what it needs (cigar, flags, strand, mapq, etc.) in the ActiveRecord — NOT perform repeated store lookups for the same record in the hot loop.
Since BAM records arrive in coordinate-sorted order from fetch_into, the pileup engine MUST NOT sort record indices. It MUST iterate records in arena order directly.
Building a CigarMapping MUST NOT clone the CIGAR ops via .to_vec(). The typed CIGAR ops live in the arena slab for the lifetime of the region (see r[record_store.slim_record.field_getters]); CigarMapping::new MUST take a borrowed &[CigarOp] and either pre-extract a small CompactOp array (Complex path) or compute summary state without copying the ops (Linear path).
Matches and indels counts MUST be computed once per record during decode and stored in SlimRecord, NOT recomputed from CIGAR at every pileup position.
For records with more than 4 CIGAR operations, qpos_at SHOULD use binary search on ref_start instead of linear scan. For 1–4 ops, linear scan is acceptable.
The RecordStore MUST support a capacity hint so that the first region's allocation can be pre-sized based on an estimate (e.g., from the BAI index chunk sizes), avoiding repeated reallocation during the first fetch_into. This is provided by RecordStore::with_byte_hint().