diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index e3534a7bc..6f33b91e8 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -57,13 +57,14 @@ impl<'a> Benchmark<'a> { fn run_intermediate_command( &self, command: &Command<'_>, + iteration: executor::BenchmarkIteration, error_output: &'static str, output_policy: &CommandOutputPolicy, ) -> Result { self.executor .run_command_and_measure( command, - executor::BenchmarkIteration::NonBenchmarkRun, + iteration, Some(CmdFailureAction::RaiseError), output_policy, ) @@ -87,7 +88,14 @@ impl<'a> Benchmark<'a> { Append ' || true' to the command if you are sure that this can be ignored."; Ok(command - .map(|cmd| self.run_intermediate_command(&cmd, error_output, output_policy)) + .map(|cmd| { + self.run_intermediate_command( + &cmd, + executor::BenchmarkIteration::NonBenchmarkRun, + error_output, + output_policy, + ) + }) .transpose()? .unwrap_or_default()) } @@ -108,7 +116,14 @@ impl<'a> Benchmark<'a> { Append ' || true' to the command if you are sure that this can be ignored."; Ok(command - .map(|cmd| self.run_intermediate_command(&cmd, error_output, output_policy)) + .map(|cmd| { + self.run_intermediate_command( + &cmd, + executor::BenchmarkIteration::NonBenchmarkRun, + error_output, + output_policy, + ) + }) .transpose()? .unwrap_or_default()) } @@ -117,24 +132,26 @@ impl<'a> Benchmark<'a> { fn run_preparation_command( &self, command: &Command<'_>, + iteration: executor::BenchmarkIteration, output_policy: &CommandOutputPolicy, ) -> Result { let error_output = "The preparation command terminated with a non-zero exit code. \ Append ' || true' to the command if you are sure that this can be ignored."; - self.run_intermediate_command(command, error_output, output_policy) + self.run_intermediate_command(command, iteration, error_output, output_policy) } /// Run the command specified by `--conclude`. fn run_conclusion_command( &self, command: &Command<'_>, + iteration: executor::BenchmarkIteration, output_policy: &CommandOutputPolicy, ) -> Result { let error_output = "The conclusion command terminated with a non-zero exit code. \ Append ' || true' to the command if you are sure that this can be ignored."; - self.run_intermediate_command(command, error_output, output_policy) + self.run_intermediate_command(command, iteration, error_output, output_policy) } /// Run the benchmark for a single command @@ -170,10 +187,10 @@ impl<'a> Benchmark<'a> { ) }); - let run_preparation_command = || { + let run_preparation_command = |iteration: BenchmarkIteration| { preparation_command .as_ref() - .map(|cmd| self.run_preparation_command(cmd, output_policy)) + .map(|cmd| self.run_preparation_command(cmd, iteration, output_policy)) .transpose() }; @@ -189,10 +206,10 @@ impl<'a> Benchmark<'a> { self.command.get_parameters().iter().cloned(), ) }); - let run_conclusion_command = || { + let run_conclusion_command = |iteration: BenchmarkIteration| { conclusion_command .as_ref() - .map(|cmd| self.run_conclusion_command(cmd, output_policy)) + .map(|cmd| self.run_conclusion_command(cmd, iteration, output_policy)) .transpose() }; @@ -211,14 +228,14 @@ impl<'a> Benchmark<'a> { }; for i in 0..self.options.warmup_count { - let _ = run_preparation_command()?; + let _ = run_preparation_command(BenchmarkIteration::Warmup(i))?; let _ = self.executor.run_command_and_measure( self.command, BenchmarkIteration::Warmup(i), None, output_policy, )?; - let _ = run_conclusion_command()?; + let _ = run_conclusion_command(BenchmarkIteration::Warmup(i))?; if let Some(bar) = progress_bar.as_ref() { bar.inc(1) } @@ -239,7 +256,7 @@ impl<'a> Benchmark<'a> { None }; - let preparation_result = run_preparation_command()?; + let preparation_result = run_preparation_command(BenchmarkIteration::Benchmark(0))?; let preparation_overhead = preparation_result.map_or(0.0, |res| res.time_real + self.executor.time_overhead()); @@ -252,7 +269,7 @@ impl<'a> Benchmark<'a> { )?; let success = status.success(); - let conclusion_result = run_conclusion_command()?; + let conclusion_result = run_conclusion_command(BenchmarkIteration::Benchmark(0))?; let conclusion_overhead = conclusion_result.map_or(0.0, |res| res.time_real + self.executor.time_overhead()); @@ -295,7 +312,7 @@ impl<'a> Benchmark<'a> { // Gather statistics (perform the actual benchmark) for i in 0..count_remaining { - run_preparation_command()?; + run_preparation_command(BenchmarkIteration::Benchmark(i + 1))?; let msg = { let mean = format_duration(mean(×_real), self.options.time_unit); @@ -326,7 +343,7 @@ impl<'a> Benchmark<'a> { bar.inc(1) } - run_conclusion_command()?; + run_conclusion_command(BenchmarkIteration::Benchmark(i + 1))?; } if let Some(bar) = progress_bar.as_ref() { diff --git a/tests/execution_order_tests.rs b/tests/execution_order_tests.rs index 6ccc2e5ed..f97b6ede1 100644 --- a/tests/execution_order_tests.rs +++ b/tests/execution_order_tests.rs @@ -327,6 +327,28 @@ fn setup_prepare_conclude_cleanup_combined() { .run(); } +#[test] +fn prepare_and_conclude_see_the_current_hyperfine_iteration() { + ExecutionOrderTest::new() + .arg("--warmup=1") + .arg("--runs=2") + .prepare("prep=${HYPERFINE_ITERATION}") + .command("main=${HYPERFINE_ITERATION}") + .conclude("conc=${HYPERFINE_ITERATION}") + // warmup + .expect_output("prep=warmup-0") + .expect_output("main=warmup-0") + .expect_output("conc=warmup-0") + // benchmark + .expect_output("prep=0") + .expect_output("main=0") + .expect_output("conc=0") + .expect_output("prep=1") + .expect_output("main=1") + .expect_output("conc=1") + .run(); +} + #[test] fn single_parameter_value() { ExecutionOrderTest::new()