Skip to main content

bench_min_rotational_hamming/
bench_min_rotational_hamming.rs

1//! Micro-benchmark for `min_rotational_hamming_distance`.
2//!
3//! Mirrors the three scenarios in the Scala twin's ComparingBench:
4//!   * rotation  — best case, distance 0 (`a` vs a rotation of `a`)
5//!   * oneOff    — mid case, distance 1
6//!   * reversed  — worst case, distance close to `n`
7//!
8//! Run with: `cargo run --release --example bench_min_rotational_hamming`.
9//!
10//! Note: this example needs Rust 1.66+ for `std::hint::black_box`. The
11//! library itself keeps its 1.63 MSRV; examples are dev-only targets and
12//! are never built by crate consumers.
13#![allow(clippy::incompatible_msrv)]
14
15use std::hint::black_box;
16use std::time::Instant;
17
18use ring_seq::AsCircular;
19
20fn rotated(a: &[u32], k: usize) -> Vec<u32> {
21    let n = a.len();
22    (0..n).map(|i| a[(i + k) % n]).collect()
23}
24
25fn one_off(a: &[u32]) -> Vec<u32> {
26    let mut v = a.to_vec();
27    if !v.is_empty() {
28        v[0] = v[0].wrapping_add(1);
29    }
30    v
31}
32
33fn reversed(a: &[u32]) -> Vec<u32> {
34    let mut v = a.to_vec();
35    v.reverse();
36    v
37}
38
39fn bench_case(label: &str, n: usize, iters: u64, a: &[u32], b: &[u32]) {
40    // warm-up
41    for _ in 0..(iters / 10).max(1) {
42        black_box(a.circular().min_rotational_hamming_distance(black_box(b)));
43    }
44    let start = Instant::now();
45    let mut acc: usize = 0;
46    for _ in 0..iters {
47        acc = acc.wrapping_add(black_box(
48            a.circular().min_rotational_hamming_distance(black_box(b)),
49        ));
50    }
51    let elapsed = start.elapsed();
52    let ns_per_op = elapsed.as_nanos() as f64 / iters as f64;
53    println!(
54        "{:<10} n={:<5} iters={:<10} total={:>10.3?} ns/op={:>12.0} (acc={})",
55        label, n, iters, elapsed, ns_per_op, acc
56    );
57}
58
59fn iters_for(n: usize) -> u64 {
60    match n {
61        16 => 1_000_000,
62        256 => 10_000,
63        4096 => 50,
64        _ => 1_000,
65    }
66}
67
68fn main() {
69    for &n in &[16usize, 256, 4096] {
70        let base: Vec<u32> = (0..n as u32).collect();
71        let rot = rotated(&base, n / 3);
72        let off = one_off(&base);
73        let rev = reversed(&base);
74        let iters = iters_for(n);
75
76        bench_case("rotation", n, iters, &base, &rot);
77        bench_case("oneOff  ", n, iters, &base, &off);
78        bench_case("reversed", n, iters, &base, &rev);
79        println!();
80    }
81}