From 0ea09bdf826d13b1f2d01e1e6853e8be6c3d780d Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 14 May 2026 12:22:38 -0600 Subject: [PATCH] perf(hype): reuse the per-sample dominators buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `estimate_contributions` heap-allocated a fresh `dominators: Vec` on every Monte Carlo sample — thousands of alloc/free pairs per call. Hoist it out of the sample loop and `clear()` it each iteration. Bit-identical. In the compare_profile benchmark this removed ~4.2M malloc/free pairs, dropping `malloc` + `free` self-Ir by ~0.24B. --- src/algorithms/hype.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/algorithms/hype.rs b/src/algorithms/hype.rs index 77b4a94..db88973 100644 --- a/src/algorithms/hype.rs +++ b/src/algorithms/hype.rs @@ -416,6 +416,9 @@ fn estimate_contributions( let mut contrib = vec![0.0_f64; n]; let mut sample = vec![0.0_f64; m]; + // Reused across samples — previously heap-allocated once per Monte + // Carlo sample (thousands of allocations per call). + let mut dominators: Vec = Vec::with_capacity(n); for _ in 0..samples { for k in 0..m { let u: f64 = rng.random(); @@ -423,7 +426,7 @@ fn estimate_contributions( } // Count and identify candidates that dominate this sample (point // in the box). - let mut dominators: Vec = Vec::with_capacity(n); + dominators.clear(); for (i, o) in oriented.iter().enumerate() { if o.iter().zip(sample.iter()).all(|(p, s)| *p <= *s) { dominators.push(i); @@ -436,7 +439,7 @@ fn estimate_contributions( // dominators. (This generalizes "exactly-one dominator" to // arbitrary multiplicities.) let weight = 1.0 / dominators.len() as f64; - for i in dominators { + for &i in &dominators { contrib[i] += weight; } }