use std::hint::black_box;
use std::time::Instant;
const N: usize = 5_000_000;
fn pool() -> Vec<String> {
vec![
"Main".to_string(),
"Oak".to_string(),
"Pine".to_string(),
"Elm".to_string(),
"Maple".to_string(),
]
}
fn build_row(buf: &mut Vec<u8>, i: usize, streets: &[String]) {
let num = 100 + (i % 9900);
let s = num.to_string();
buf.extend_from_slice(s.as_bytes());
buf.push(b' ');
buf.extend_from_slice(streets[i % streets.len()].as_bytes());
buf.push(b' ');
buf.extend_from_slice(b"St");
}
fn run_checked(streets: &[String]) -> u64 {
let mut buf: Vec<u8> = Vec::with_capacity(32);
let mut acc: u64 = 0;
for i in 0..N {
buf.clear();
build_row(&mut buf, i, streets);
let s = std::str::from_utf8(&buf).unwrap();
acc = acc.wrapping_add(s.len() as u64);
}
acc
}
fn run_unchecked(streets: &[String]) -> u64 {
let mut buf: Vec<u8> = Vec::with_capacity(32);
let mut acc: u64 = 0;
for i in 0..N {
buf.clear();
build_row(&mut buf, i, streets);
debug_assert!(std::str::from_utf8(&buf).is_ok());
let s = unsafe { std::str::from_utf8_unchecked(&buf) };
acc = acc.wrapping_add(s.len() as u64);
}
acc
}
fn main() {
let streets = pool();
black_box(run_checked(&streets));
black_box(run_unchecked(&streets));
for iter in 0..5 {
let t = Instant::now();
let a = black_box(run_checked(&streets));
let ta = t.elapsed().as_secs_f64() * 1000.0;
let t = Instant::now();
let b = black_box(run_unchecked(&streets));
let tb = t.elapsed().as_secs_f64() * 1000.0;
assert_eq!(a, b, "checksum mismatch — checked vs unchecked disagree");
println!(
"iter {iter}: checked={ta:.1} ms | unchecked={tb:.1} ms | speedup={:.3}x",
ta / tb
);
}
}