use tagged_pointer_as_enum::{tagged_enum, TaggedPointerValue}; #[cfg(feature = "bench")] extern crate criterion; #[cfg(feature = "bench")] use criterion::{black_box, criterion_group, criterion_main, Criterion}; struct None; impl TaggedPointerValue for None {} enum Native { None(None), U8(Box), U16(Box), U32(Box), U64(Box), I8(Box), I16(Box), I32(Box), } impl Default for Native { fn default() -> Self { Native::None(None) } } tagged_enum! { enum Tagged { bits = 8; None(None), U8(Box), U16(Box), U32(Box), U64(Box), I8(Box), I16(Box), I32(Box), } } impl Default for Tagged { fn default() -> Self { Tagged::None(None) } } trait ForEachVariant { fn for_each_variant(f: F) where F: FnMut(Self), Self: Sized; } impl ForEachVariant for Native { fn for_each_variant(mut f: F) where F: FnMut(Self), { f(Native::U8(Box::new(10))); f(Native::U16(Box::new(1000))); f(Native::U32(Box::new(100_000))); f(Native::U64(Box::new(100_000))); f(Native::I8(Box::new(-10))); f(Native::I16(Box::new(-1000))); f(Native::I32(Box::new(-100_000))); } } impl ForEachVariant for Tagged { fn for_each_variant(mut f: F) where F: FnMut(Self), { f(Tagged::U8(Box::new(10))); f(Tagged::U16(Box::new(1000))); f(Tagged::U32(Box::new(100_000))); f(Tagged::U64(Box::new(100_000))); f(Tagged::I8(Box::new(-10))); f(Tagged::I16(Box::new(-1000))); f(Tagged::I32(Box::new(-100_000))); } } fn work() where T: ForEachVariant + Default, { let mut stack = Vec::with_capacity(7 * 50); for _ in 0..50 { T::for_each_variant(|v| { stack.push(v); let len = stack.len(); std::mem::take(&mut stack[len - 1]); }); } #[cfg(feature = "bench")] black_box(stack); } #[inline(never)] #[cfg(feature = "bench")] fn native_enum(c: &mut Criterion) { c.bench_function("native_enum", |b| b.iter(|| work::())); } #[inline(never)] #[cfg(feature = "bench")] fn tagged_enum(c: &mut Criterion) { c.bench_function("tagged_enum", |b| b.iter(|| work::())); } #[cfg(feature = "bench")] criterion_group!(alloc, native_enum, tagged_enum); #[cfg(feature = "bench")] criterion_main!(alloc); #[cfg(not(feature = "bench"))] fn main() {}