Skip to content

Instantly share code, notes, and snippets.

@Nekrolm
Last active May 17, 2026 10:11
Show Gist options
  • Select an option

  • Save Nekrolm/3c56ad837224a8ca9dc91f82b84a8f83 to your computer and use it in GitHub Desktop.

Select an option

Save Nekrolm/3c56ad837224a8ca9dc91f82b84a8f83 to your computer and use it in GitHub Desktop.
use bumpalo::Bump;
use criterion::{criterion_group, criterion_main, Criterion};
use std::hint::black_box;
const N: usize = 10000;
const NUM_IMPLS: usize = 5;
pub trait Handler {
fn handle(&mut self) -> u64;
}
macro_rules! define_impl {
($name:ident, $idx:expr) => {
pub struct $name {
state: u64,
}
impl $name {
fn new(seed: u64) -> Self {
Self { state: seed }
}
}
impl Handler for $name {
fn handle(&mut self) -> u64 {
let mut x = self.state;
x = x.wrapping_add($idx as u64);
x = x.wrapping_mul(1664525u64.wrapping_add($idx as u64 * 37));
x ^= x.rotate_left((($idx * 7) % 63) as u32);
self.state = x.wrapping_add(0x9e37_79b9_7f4a_7c15u64.wrapping_mul($idx as u64));
self.state
}
}
};
}
define_impl!(Impl1, 1);
define_impl!(Impl2, 2);
define_impl!(Impl3, 3);
define_impl!(Impl4, 4);
define_impl!(Impl5, 5);
// define_impl!(Impl6, 6);
// define_impl!(Impl7, 7);
// define_impl!(Impl8, 8);
// define_impl!(Impl9, 9);
// define_impl!(Impl10, 10);
// define_impl!(Impl11, 11);
// define_impl!(Impl12, 12);
// define_impl!(Impl13, 13);
// define_impl!(Impl14, 14);
// define_impl!(Impl15, 15);
// define_impl!(Impl16, 16);
// define_impl!(Impl17, 17);
// define_impl!(Impl18, 18);
// define_impl!(Impl19, 19);
// define_impl!(Impl20, 20);
pub enum HandleEnum<'a> {
I1(&'a mut Impl1),
I2(&'a mut Impl2),
I3(&'a mut Impl3),
I4(&'a mut Impl4),
I5(&'a mut Impl5),
// I6(&'a mut Impl6),
// I7(&'a mut Impl7),
// I8(&'a mut Impl8),
// I9(&'a mut Impl9),
// I10(&'a mut Impl10),
// I11(&'a mut Impl11),
// I12(&'a mut Impl12),
// I13(&'a mut Impl13),
// I14(&'a mut Impl14),
// I15(&'a mut Impl15),
// I16(&'a mut Impl16),
// I17(&'a mut Impl17),
// I18(&'a mut Impl18),
// I19(&'a mut Impl19),
// I20(&'a mut Impl20),
}
impl<'a> HandleEnum<'a> {
pub fn call(&mut self) -> u64 {
match self {
HandleEnum::I1(v) => v.handle(),
HandleEnum::I2(v) => v.handle(),
HandleEnum::I3(v) => v.handle(),
HandleEnum::I4(v) => v.handle(),
HandleEnum::I5(v) => v.handle(),
// HandleEnum::I6(v) => v.handle(),
// HandleEnum::I7(v) => v.handle(),
// HandleEnum::I8(v) => v.handle(),
// HandleEnum::I9(v) => v.handle(),
// HandleEnum::I10(v) => v.handle(),
// HandleEnum::I11(v) => v.handle(),
// HandleEnum::I12(v) => v.handle(),
// HandleEnum::I13(v) => v.handle(),
// HandleEnum::I14(v) => v.handle(),
// HandleEnum::I15(v) => v.handle(),
// HandleEnum::I16(v) => v.handle(),
// HandleEnum::I17(v) => v.handle(),
// HandleEnum::I18(v) => v.handle(),
// HandleEnum::I19(v) => v.handle(),
// HandleEnum::I20(v) => v.handle(),
}
}
}
fn lcg_next(seed: &mut u64) {
*seed = seed.wrapping_mul(6364136223846793005u64).wrapping_add(1);
}
fn make_enum_vec<'a>(bump: &'a Bump) -> Vec<HandleEnum<'a>> {
let mut v = Vec::with_capacity(N);
let mut seed: u64 = 0x1234_5678_9ABC_DEF0u64;
for i in 0..N {
lcg_next(&mut seed);
let choice = ((seed >> 32) as usize) % NUM_IMPLS;
match choice {
0 => {
let obj = bump.alloc(Impl1::new(seed ^ i as u64));
v.push(HandleEnum::I1(obj));
}
1 => {
let obj = bump.alloc(Impl2::new(seed ^ i as u64));
v.push(HandleEnum::I2(obj));
}
2 => {
let obj = bump.alloc(Impl3::new(seed ^ i as u64));
v.push(HandleEnum::I3(obj));
}
3 => {
let obj = bump.alloc(Impl4::new(seed ^ i as u64));
v.push(HandleEnum::I4(obj));
}
4 => {
let obj = bump.alloc(Impl5::new(seed ^ i as u64));
v.push(HandleEnum::I5(obj));
}
// 5 => {
// let obj = bump.alloc(Impl6::new(seed ^ i as u64));
// v.push(HandleEnum::I6(obj));
// }
// 6 => {
// let obj = bump.alloc(Impl7::new(seed ^ i as u64));
// v.push(HandleEnum::I7(obj));
// }
// 7 => {
// let obj = bump.alloc(Impl8::new(seed ^ i as u64));
// v.push(HandleEnum::I8(obj));
// }
// 8 => {
// let obj = bump.alloc(Impl9::new(seed ^ i as u64));
// v.push(HandleEnum::I9(obj));
// }
// 9 => {
// let obj = bump.alloc(Impl10::new(seed ^ i as u64));
// v.push(HandleEnum::I10(obj));
// }
// 10 => {
// let obj = bump.alloc(Impl11::new(seed ^ i as u64));
// v.push(HandleEnum::I11(obj));
// }
// 11 => {
// let obj = bump.alloc(Impl12::new(seed ^ i as u64));
// v.push(HandleEnum::I12(obj));
// }
// 12 => {
// let obj = bump.alloc(Impl13::new(seed ^ i as u64));
// v.push(HandleEnum::I13(obj));
// }
// 13 => {
// let obj = bump.alloc(Impl14::new(seed ^ i as u64));
// v.push(HandleEnum::I14(obj));
// }
// 14 => {
// let obj = bump.alloc(Impl15::new(seed ^ i as u64));
// v.push(HandleEnum::I15(obj));
// }
// 15 => {
// let obj = bump.alloc(Impl16::new(seed ^ i as u64));
// v.push(HandleEnum::I16(obj));
// }
// 16 => {
// let obj = bump.alloc(Impl17::new(seed ^ i as u64));
// v.push(HandleEnum::I17(obj));
// }
// 17 => {
// let obj = bump.alloc(Impl18::new(seed ^ i as u64));
// v.push(HandleEnum::I18(obj));
// }
// 18 => {
// let obj = bump.alloc(Impl19::new(seed ^ i as u64));
// v.push(HandleEnum::I19(obj));
// }
// 19 => {
// let obj = bump.alloc(Impl20::new(seed ^ i as u64));
// v.push(HandleEnum::I20(obj));
// }
_ => unreachable!(),
}
}
v
}
fn make_dyn_vec<'a>(bump: &'a Bump) -> Vec<&'a mut dyn Handler> {
let mut v: Vec<&'a mut dyn Handler> = Vec::with_capacity(N);
let mut seed: u64 = 0x1234_5678_9ABC_DEF0u64;
for i in 0..N {
lcg_next(&mut seed);
let choice = ((seed >> 32) as usize) % NUM_IMPLS;
match choice {
0 => {
let obj = bump.alloc(Impl1::new(seed ^ i as u64));
v.push(obj as &mut dyn Handler);
}
1 => {
let obj = bump.alloc(Impl2::new(seed ^ i as u64));
v.push(obj as &mut dyn Handler);
}
2 => {
let obj = bump.alloc(Impl3::new(seed ^ i as u64));
v.push(obj as &mut dyn Handler);
}
3 => {
let obj = bump.alloc(Impl4::new(seed ^ i as u64));
v.push(obj as &mut dyn Handler);
}
4 => {
let obj = bump.alloc(Impl5::new(seed ^ i as u64));
v.push(obj as &mut dyn Handler);
}
// 5 => {
// let obj = bump.alloc(Impl6::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 6 => {
// let obj = bump.alloc(Impl7::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 7 => {
// let obj = bump.alloc(Impl8::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 8 => {
// let obj = bump.alloc(Impl9::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 9 => {
// let obj = bump.alloc(Impl10::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 10 => {
// let obj = bump.alloc(Impl11::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 11 => {
// let obj = bump.alloc(Impl12::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 12 => {
// let obj = bump.alloc(Impl13::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 13 => {
// let obj = bump.alloc(Impl14::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 14 => {
// let obj = bump.alloc(Impl15::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 15 => {
// let obj = bump.alloc(Impl16::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 16 => {
// let obj = bump.alloc(Impl17::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 17 => {
// let obj = bump.alloc(Impl18::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 18 => {
// let obj = bump.alloc(Impl19::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
// 19 => {
// let obj = bump.alloc(Impl20::new(seed ^ i as u64));
// v.push(obj as &mut dyn Handler);
// }
_ => unreachable!(),
}
}
v
}
fn bench_enum(c: &mut Criterion) {
let mut group = c.benchmark_group("dispatch_enum");
group.sample_size(200);
let bump = Bump::new();
let mut items = make_enum_vec(&bump);
group.bench_function("enum_dispatch", |b| {
b.iter(|| {
let mut sum: u64 = 0;
for it in items.iter_mut() {
sum = sum.wrapping_add(it.call());
}
black_box(sum);
})
});
group.finish();
}
fn bench_dyn(c: &mut Criterion) {
let mut group = c.benchmark_group("dispatch_dyn");
group.sample_size(200);
let bump = Bump::new();
let mut items = make_dyn_vec(&bump);
group.bench_function("dyn_dispatch", |b| {
b.iter(|| {
let mut sum: u64 = 0;
for it in items.iter_mut() {
sum = sum.wrapping_add(it.handle());
}
black_box(sum);
})
});
group.finish();
}
criterion_group!(benches, bench_dyn, bench_enum);
criterion_main!(benches);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment