Skip to content

Commit 25f20a8

Browse files
committed
add NUM_ITER_GROUP parameter
1 parent 35df514 commit 25f20a8

3 files changed

Lines changed: 112 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
Unreleased (2026-04-08)
2-
==================
1+
Unreleased
2+
==========
3+
### Features
4+
- Added `NUM_ITER_GROUP` environment variable to override benchmark group iterations
5+
6+
0.16.0 (2026-04-12)
7+
===================
38
### Features
49
- Advanced filtering engine via `tantivy-query-grammar`
510
```

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@ BINGGAN_FILTER="my_bench OR other_bench" cargo bench
123123

124124
Available fields are `runner_name` (or `r`), `group_name` (or `g`), and `bench_name` (or `b`). If no field is specified, it will match against the full generated `BenchId`.
125125

126+
### Iteration overrides
127+
128+
If you want reproducible iteration counts without changing code, you can override them with environment variables:
129+
130+
```bash
131+
NUM_ITER_BENCH=100 cargo bench
132+
NUM_ITER_GROUP=16 cargo bench
133+
NUM_ITER_GROUP=16 NUM_ITER_BENCH=100 cargo bench
134+
```
135+
136+
- `NUM_ITER_BENCH` sets the inner benchmark iteration count.
137+
- `NUM_ITER_GROUP` sets how often the whole benchmark group is repeated.
138+
126139
### Perf Integration
127140
Perf may run into limitations where all counters are reported as zero. https://github.com/jimblandy/perf-event/issues/2
128141
Disabling the NMI watchdog should help:

src/config.rs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ impl Config {
6161
}
6262

6363
/// Returns the number of iterations for the group.
64+
///
65+
/// If the `NUM_ITER_GROUP` environment variable is set, it takes precedence.
6466
pub fn get_num_iter_for_group(&self) -> usize {
65-
self.num_iter_group.unwrap_or(32)
67+
num_iter_from_env("NUM_ITER_GROUP")
68+
.or(self.num_iter_group)
69+
.unwrap_or(32)
6670
}
6771

6872
/// Manully set the number of iterations the benchmark group is run.
@@ -101,6 +105,12 @@ impl Config {
101105
}
102106
}
103107

108+
fn num_iter_from_env(var_name: &str) -> Option<usize> {
109+
std::env::var(var_name)
110+
.ok()
111+
.and_then(|val| val.parse::<usize>().ok())
112+
}
113+
104114
pub(crate) fn parse_args() -> Config {
105115
let res = opts! {
106116
synopsis "";
@@ -129,3 +139,84 @@ pub(crate) fn parse_args() -> Config {
129139
unreachable!();
130140
}
131141
}
142+
143+
#[cfg(test)]
144+
mod tests {
145+
use super::*;
146+
use std::sync::{LazyLock, Mutex};
147+
148+
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
149+
150+
struct EnvVarGuard {
151+
key: &'static str,
152+
original_value: Option<String>,
153+
}
154+
155+
impl EnvVarGuard {
156+
fn set(key: &'static str, value: &str) -> Self {
157+
let original_value = std::env::var(key).ok();
158+
// SAFETY: The tests serialize environment mutations with ENV_LOCK and restore the
159+
// previous state before releasing the lock.
160+
unsafe { std::env::set_var(key, value) };
161+
Self {
162+
key,
163+
original_value,
164+
}
165+
}
166+
167+
fn unset(key: &'static str) -> Self {
168+
let original_value = std::env::var(key).ok();
169+
// SAFETY: The tests serialize environment mutations with ENV_LOCK and restore the
170+
// previous state before releasing the lock.
171+
unsafe { std::env::remove_var(key) };
172+
Self {
173+
key,
174+
original_value,
175+
}
176+
}
177+
}
178+
179+
impl Drop for EnvVarGuard {
180+
fn drop(&mut self) {
181+
// SAFETY: The tests serialize environment mutations with ENV_LOCK and restore the
182+
// previous state before releasing the lock.
183+
unsafe {
184+
if let Some(value) = &self.original_value {
185+
std::env::set_var(self.key, value);
186+
} else {
187+
std::env::remove_var(self.key);
188+
}
189+
}
190+
}
191+
}
192+
193+
#[test]
194+
fn num_iter_group_env_overrides_config() {
195+
let _env_lock = ENV_LOCK.lock().unwrap();
196+
let _env_guard = EnvVarGuard::set("NUM_ITER_GROUP", "17");
197+
198+
let mut config = Config::default();
199+
config.set_num_iter_for_group(9);
200+
201+
assert_eq!(config.get_num_iter_for_group(), 17);
202+
}
203+
204+
#[test]
205+
fn invalid_num_iter_group_env_falls_back_to_config() {
206+
let _env_lock = ENV_LOCK.lock().unwrap();
207+
let _env_guard = EnvVarGuard::set("NUM_ITER_GROUP", "invalid");
208+
209+
let mut config = Config::default();
210+
config.set_num_iter_for_group(9);
211+
212+
assert_eq!(config.get_num_iter_for_group(), 9);
213+
}
214+
215+
#[test]
216+
fn num_iter_group_defaults_to_32() {
217+
let _env_lock = ENV_LOCK.lock().unwrap();
218+
let _env_guard = EnvVarGuard::unset("NUM_ITER_GROUP");
219+
220+
assert_eq!(Config::default().get_num_iter_for_group(), 32);
221+
}
222+
}

0 commit comments

Comments
 (0)