diff --git a/src/commands/clip.rs b/src/commands/clip.rs index b5229f2d6..3854583ee 100644 --- a/src/commands/clip.rs +++ b/src/commands/clip.rs @@ -175,7 +175,8 @@ struct ClipProcessedBatch { impl MemoryEstimate for ClipProcessedBatch { fn estimate_heap_size(&self) -> usize { - self.clipped_records.iter().map(MemoryEstimate::estimate_heap_size).sum() + self.clipped_records.iter().map(MemoryEstimate::estimate_heap_size).sum::() + + self.clipped_records.capacity() * std::mem::size_of::() } } @@ -2462,4 +2463,29 @@ mod tests { Ok(()) } + + #[test] + fn test_clip_processed_batch_memory_estimate() { + use fgumi_lib::sam::builder::RecordBuilder; + use noodles::sam::alignment::record_buf::RecordBuf; + + let record = RecordBuilder::new().sequence("ACGT").qualities(&[30, 30, 30, 30]).build(); + let mut records = Vec::with_capacity(10); + records.push(record); + + let batch = ClipProcessedBatch { + clipped_records: records, + templates_count: 1, + overlap_clipped_count: 0, + extend_clipped_count: 0, + }; + + let estimate = batch.estimate_heap_size(); + // Should include Vec overhead for capacity * size_of::() + let vec_overhead = 10 * std::mem::size_of::(); + assert!( + estimate >= vec_overhead, + "estimate {estimate} should include Vec overhead {vec_overhead}" + ); + } } diff --git a/src/commands/codec.rs b/src/commands/codec.rs index a5fc71299..9b9ac3ef6 100644 --- a/src/commands/codec.rs +++ b/src/commands/codec.rs @@ -60,7 +60,9 @@ struct CodecProcessedBatch { impl MemoryEstimate for CodecProcessedBatch { fn estimate_heap_size(&self) -> usize { - self.consensus_output.data.len() + self.rejects.iter().map(Vec::len).sum::() + self.consensus_output.data.capacity() + + self.rejects.iter().map(Vec::capacity).sum::() + + self.rejects.capacity() * std::mem::size_of::>() } } @@ -1185,4 +1187,23 @@ mod tests { Ok(()) } + + #[test] + fn test_codec_processed_batch_memory_estimate() { + let mut data = Vec::with_capacity(1024); + data.extend_from_slice(&[0u8; 100]); + let mut reject = Vec::with_capacity(512); + reject.extend_from_slice(&[0u8; 50]); + + let batch = CodecProcessedBatch { + consensus_output: ConsensusOutput { data, count: 1 }, + rejects: vec![reject], + groups_count: 1, + stats: CodecConsensusStats::default(), + }; + + let estimate = batch.estimate_heap_size(); + assert!(estimate >= 1024 + 512, "estimate {estimate} should be >= 1536 (capacities)"); + assert!(estimate > 1024 + 512, "estimate {estimate} should include Vec overhead"); + } } diff --git a/src/commands/dedup.rs b/src/commands/dedup.rs index 3ec488777..26e70e452 100644 --- a/src/commands/dedup.rs +++ b/src/commands/dedup.rs @@ -186,6 +186,7 @@ impl BatchWeight for ProcessedDedupGroup { impl MemoryEstimate for ProcessedDedupGroup { fn estimate_heap_size(&self) -> usize { self.templates.iter().map(MemoryEstimate::estimate_heap_size).sum::() + + self.templates.capacity() * std::mem::size_of::