Performance Considerations
Optimizing DSP performance in bbx_audio.
Key Metrics
| Metric | Target |
|---|---|
| Latency | < 1 buffer |
| CPU usage | < 50% of budget |
| Memory | Predictable, fixed |
| Allocation | Zero during process |
Optimization Strategies
Pre-computation
Calculate once, use many times:
#![allow(unused)] fn main() { // In prepare() self.coefficient = calculate_filter_coeff(self.cutoff, context.sample_rate); // In process() - just use it output = input * self.coefficient + self.state; }
Cache Efficiency
Keep hot data together:
#![allow(unused)] fn main() { // Good: Contiguous buffer storage audio_buffers: Vec<AudioBuffer<S>> // Good: Sequential processing for block_id in &self.execution_order { self.process_block(*block_id); } }
Branch Avoidance
Prefer branchless code:
#![allow(unused)] fn main() { // Avoid if condition { result = a; } else { result = b; } // Prefer let mask = condition as f32; // 0.0 or 1.0 result = a * mask + b * (1.0 - mask); }
SIMD Potential
Design for SIMD:
- Process 4+ samples at once
- Align buffers to 16/32 bytes
- Avoid data-dependent branches
Profiling
Measure before optimizing:
#![allow(unused)] fn main() { #[cfg(feature = "profiling")] let _span = tracing::span!(tracing::Level::TRACE, "process_block"); }
Common Bottlenecks
- Memory allocation in audio thread
- Cache misses from scattered data
- Branch misprediction in complex logic
- Function call overhead for tiny operations
- Denormal processing in filter feedback