everscale-types 0.1.2

A set of primitive types and utilities for the Everscale blockchain.
Documentation
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<RefsIter<'a>>,
}

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);