Hone logo
Hone
Problems

Rust Performance Benchmarking Tool

This challenge asks you to build a lightweight benchmarking tool in Rust. Developing efficient code is crucial, and having a reliable way to measure the performance of different code sections or algorithms is essential for optimization. You will create a system that can time the execution of user-provided code snippets.

Problem Description

You need to implement a Rust crate that provides a simple benchmarking framework. This framework should allow users to define functions and then measure how long it takes for these functions to execute a specified number of times. The core functionality should be to:

  1. Define Benchmarks: Allow users to register functions that they want to benchmark.
  2. Run Benchmarks: Execute a registered benchmark a configurable number of times.
  3. Measure Execution Time: Accurately record the total time taken for all iterations of a benchmark.
  4. Report Results: Display the average execution time per iteration for each benchmark.

Key Requirements:

  • The benchmarking tool should be implemented as a Rust library (a crate).
  • Users should be able to define a function (or a closure) that represents the code to be benchmarked.
  • The number of iterations for each benchmark run should be configurable.
  • The output should clearly show the benchmark name, the total time taken, and the average time per iteration.
  • Use std::time::Instant for precise time measurement.
  • Handle potential overhead of the benchmarking itself, though for this challenge, a simple approach is sufficient.

Expected Behavior:

When a user runs a benchmark, they should see output similar to:

Benchmarking 'my_function'...
  Total time: 1.234567 seconds
  Average time per iteration: 0.0001234567 seconds

Edge Cases:

  • Very Short Execution Times: Ensure the tool can accurately measure functions that execute extremely quickly.
  • Zero Iterations: While not explicitly useful, consider how the tool might behave if asked to run zero iterations. (Ideally, it would report no time taken or a minimal overhead).

Examples

Example 1:

// In your benchmark runner code:
// let mut bench_runner = BenchRunner::new();
// bench_runner.register("loop_add", || {
//     let mut sum = 0;
//     for i in 0..1000 {
//         sum += i;
//     }
// });
// bench_runner.run_all(100);

// Expected Output (times will vary):
// Benchmarking 'loop_add'...
//   Total time: 0.054321 seconds
//   Average time per iteration: 0.0000054321 seconds

Explanation: The loop_add function is executed 100 times. The total time and average time per iteration are calculated and displayed.

Example 2:

// In your benchmark runner code:
// let mut bench_runner = BenchRunner::new();
// bench_runner.register("fast_operation", || {
//     let x = 2 * 2;
//     let y = x + 5;
// });
// bench_runner.run_all(1_000_000);

// Expected Output (times will vary significantly):
// Benchmarking 'fast_operation'...
//   Total time: 0.123456 seconds
//   Average time per iteration: 0.000000123456 seconds

Explanation: A very fast operation is benchmarked with a large number of iterations to get a meaningful average.

Constraints

  • The core benchmarking logic must be implemented in pure Rust, utilizing the standard library.
  • The benchmark runner should be able to accept and run any FnMut() closure.
  • The number of iterations should be a usize.
  • The reported times should be in seconds, displayed with sufficient precision.

Notes

  • Consider how you will represent a benchmark (e.g., a name and a closure).
  • Think about the overall structure of the benchmarking tool: a way to add benchmarks and a way to run them.
  • For simplicity in this challenge, you do not need to worry about external factors that affect performance (like CPU throttling, other running processes, etc.) or advanced techniques like warm-up runs. The focus is on the core timing and reporting mechanism.
  • You might find it useful to create a BenchRunner struct to manage the registered benchmarks.
Loading editor...
rust