use criterion::{black_box, criterion_group, criterion_main, Criterion}; use everscale_types::cell::RefsIter; use everscale_types::prelude::*; const BOC: &str = "te6ccgECCAEAAWQAAnPP9noJKCEBL3oZerOiIcNghuL96V3wIcuYOWQdvNC+2fqCEIJDQAAAAAAAAAAAAAAAAZa8xB6QABNAAgEAUO3QlUyMI4dEepUMw3Ou6oSqq8+1lyHkjOGFK6DAn6TXAAAAAAAAAAABFP8A9KQT9LzyyAsDAgEgBwQC5vJx1wEBwADyeoMI1xjtRNCDB9cB1ws/yPgozxYjzxbJ+QADcdcBAcMAmoMH1wFRE7ry4GTegEDXAYAg1wGAINcBVBZ1+RDyqPgju/J5Zr74I4EHCKCBA+ioUiC8sfJ0AiCCEEzuZGy64w8ByMv/yz/J7VQGBQA+ghAWnj4Ruo4R+AACkyDXSpd41wHUAvsA6NGTMvI84gCYMALXTND6QIMG1wFx1wF41wHXTPgAcIAQBKoCFLHIywVQBc8WUAP6AstpItAhzzEh10mghAm5mDNwAcsAWM8WlzBxAcsAEsziyQH7AAAE0jA="; fn traverse_cell_ordinary(c: &mut Criterion) { let cell = Boc::decode_base64(BOC).unwrap(); c.bench_function("traverse cell ordinary", |b| { b.iter(|| { let mut visitor = Visitor::default(); black_box(visitor.add_cell(cell.as_ref())); }) }); } fn traverse_cell_storage_cell(c: &mut Criterion) { let cell = Boc::decode_base64(BOC).unwrap(); let usage_tree = UsageTree::new(UsageTreeMode::OnDataAccess); let cell = usage_tree.track(&cell); c.bench_function("traverse cell usage tree", |b| { b.iter(|| { let mut visitor = Visitor::default(); black_box(visitor.add_cell(cell.as_ref())); }) }); } fn traverse_cell_storage_cell_with_capacity(c: &mut Criterion) { let cell = Boc::decode_base64(BOC).unwrap(); let usage_tree = UsageTree::with_mode_and_capacity(UsageTreeMode::OnDataAccess, 100); let cell = usage_tree.track(&cell); c.bench_function("traverse cell usage tree with capacity", |b| { b.iter(|| { let mut visitor = Visitor::default(); black_box(visitor.add_cell(cell.as_ref())); }) }); } #[derive(Default)] struct Visitor<'a> { visited: ahash::HashSet<&'a HashBytes>, stack: Vec>, } impl<'a> Visitor<'a> { fn add_cell(&mut self, cell: &'a DynCell) -> bool { if !self.visited.insert(cell.repr_hash()) { return true; } self.stack.clear(); self.stack.push(cell.references()); self.reduce_stack() } fn reduce_stack(&mut self) -> bool { 'outer: while let Some(item) = self.stack.last_mut() { for cell in item.by_ref() { if !self.visited.insert(cell.repr_hash()) { continue; } let mut slice = cell.as_slice().unwrap(); slice.load_bit().ok(); slice.load_u32().ok(); slice.load_small_uint(5).ok(); slice.load_reference().ok(); let next = cell.references(); if next.peek().is_some() { self.stack.push(next); continue 'outer; } } self.stack.pop(); } true } } criterion_group!( benches, traverse_cell_ordinary, traverse_cell_storage_cell, traverse_cell_storage_cell_with_capacity ); criterion_main!(benches);