use criterion::{Criterion, criterion_group, criterion_main}; use rand::distr::{Alphanumeric, SampleString}; use smol_str::{SmolStr, StrExt, ToSmolStr, format_smolstr}; use std::hint::black_box; /// 12: small (inline) /// 50: medium (heap) /// 1000: large (heap) const TEST_LENS: [usize; 3] = [12, 50, 1000]; fn format_bench(c: &mut Criterion) { for len in TEST_LENS { let n = rand::random_range(10000..99999); let str_len = len.checked_sub(n.to_smolstr().len()).unwrap(); let str = Alphanumeric.sample_string(&mut rand::rng(), str_len); c.bench_function(&format!("format_smolstr! len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = format_smolstr!("{str}-{n}")); assert_eq!(v, format!("{str}-{n}")); }); } } fn from_str_bench(c: &mut Criterion) { for len in TEST_LENS { let str = Alphanumeric.sample_string(&mut rand::rng(), len); c.bench_function(&format!("SmolStr::from len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = SmolStr::from(black_box(&str))); assert_eq!(v, str); }); } } fn clone_bench(c: &mut Criterion) { for len in TEST_LENS { let str = Alphanumeric.sample_string(&mut rand::rng(), len); let smolstr = SmolStr::new(&str); c.bench_function(&format!("SmolStr::clone len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = smolstr.clone()); assert_eq!(v, str); }); } } fn eq_bench(c: &mut Criterion) { for len in TEST_LENS { let str = Alphanumeric.sample_string(&mut rand::rng(), len); let smolstr = SmolStr::new(&str); c.bench_function(&format!("SmolStr::eq len={len}"), |b| { let mut v = false; b.iter(|| v = smolstr == black_box(&str)); assert!(v); }); } } fn to_lowercase_bench(c: &mut Criterion) { const END_CHAR: char = 'İ'; for len in TEST_LENS { // mostly ascii seq with some non-ascii at the end let mut str = Alphanumeric.sample_string(&mut rand::rng(), len - END_CHAR.len_utf8()); str.push(END_CHAR); let str = str.as_str(); c.bench_function(&format!("to_lowercase_smolstr len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = str.to_lowercase_smolstr()); assert_eq!(v, str.to_lowercase()); }); } } fn to_ascii_lowercase_bench(c: &mut Criterion) { for len in TEST_LENS { let str = Alphanumeric.sample_string(&mut rand::rng(), len); let str = str.as_str(); c.bench_function(&format!("to_ascii_lowercase_smolstr len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = str.to_ascii_lowercase_smolstr()); assert_eq!(v, str.to_ascii_lowercase()); }); } } fn replace_bench(c: &mut Criterion) { for len in TEST_LENS { let s_dash_s = Alphanumeric.sample_string(&mut rand::rng(), len / 2) + "-" + &Alphanumeric.sample_string(&mut rand::rng(), len - 1 - len / 2); let str = s_dash_s.as_str(); c.bench_function(&format!("replace_smolstr len={len}"), |b| { let mut v = <_>::default(); b.iter(|| v = str.replace_smolstr("-", "_")); assert_eq!(v, str.replace("-", "_")); }); } } criterion_group!( benches, format_bench, from_str_bench, clone_bench, eq_bench, to_lowercase_bench, to_ascii_lowercase_bench, replace_bench, ); criterion_main!(benches);