use std::rc::Rc; use std::cell::RefCell; use std::time::Instant; thread_local! { static ARENA_INTERN: RefCell = RefCell::new(Arena1::new()); } #[allow(dead_code)] struct XXX { u: f64, a: f64, b: f64, c: f64, d: f64, } enum Val { None, N(AR1), X(XXX), } #[allow(dead_code)] enum Val2 { None, N(Rc<(Val2, Val2)>), X(XXX), } impl Val { pub fn n(a: Val, b: Val) -> Self { Val::N(AR1::new(a, b)) } pub fn x(a: f64) -> Self { let mut x = XXX::new(); x.a = a; Val::X(x) } } impl Val2 { pub fn n(a: Val2, b: Val2) -> Self { Val2::N(Rc::new((a, b))) } pub fn x(a: f64) -> Self { let mut x = XXX::new(); x.a = a; Val2::X(x) } } impl XXX { pub fn new() -> Self { Self { u: 0.0, a: 0.0, b: 0.0, c: 0.0, d: 0.0, } } } struct Arena1 { free: Vec>, } impl Arena1 { pub fn new() -> Self { let mut free = vec![]; free.resize_with(10, || Rc::new((Val::None, Val::None))); Self { free } } #[inline] pub fn alloc(&mut self) -> Rc<(Val, Val)> { if let Some(a) = self.free.pop() { a } else { Rc::new((Val::None, Val::None)) } } #[inline] pub fn free(&mut self, rc: &mut Rc<(Val, Val)>) { *Rc::get_mut(rc).unwrap() = (Val::None, Val::None); self.free.push(rc.clone()); } } #[derive(Clone)] struct AR1 { cont: Rc<(Val, Val)>, } impl AR1 { pub fn new(a: Val, b: Val) -> Self { ARENA_INTERN.with(|x| { let mut rc = x.borrow_mut().alloc(); *Rc::get_mut(&mut rc).unwrap() = (a, b); Self { cont: rc } }) } } impl Drop for AR1 { fn drop(&mut self) { if Rc::strong_count(&self.cont) == 1 { ARENA_INTERN.with(|x| { x.borrow_mut().free(&mut self.cont); }) } } } fn t1(n: usize) { let mut v = vec![]; let now = Instant::now(); for _ in 0..10000 { for _ in 0..n { v.push(Val::n(Val::x(21.32), Val::x(22.1))); } v.clear(); for _ in 0..n { v.push(Val::n(Val::x(21.32), Val::x(22.1))); } v.clear(); } println!("arena [{:5}]: {}", n, now.elapsed().as_millis()); } fn t2(n: usize) { let mut v = vec![]; let now = Instant::now(); for _ in 0..10000 { for _ in 0..n { v.push(Val2::n(Val2::x(21.32), Val2::x(22.1))); } v.clear(); for _ in 0..n { v.push(Val2::n(Val2::x(21.32), Val2::x(22.1))); } v.clear(); } println!("alloc [{:5}]: {}", n, now.elapsed().as_millis()); } fn main() { for t in 0..4 { println!("*** {}", t); t1(3000); t2(3000); t1(10); t2(10); t1(100); t2(100); t1(500); t2(500); t1(1000); t2(1000); } }