Skip to content

Commit

Permalink
Merge branch 'tycho'
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed Jun 10, 2024
2 parents 0abd815 + 5f1326c commit 0823574
Show file tree
Hide file tree
Showing 29 changed files with 2,326 additions and 530 deletions.
11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["Ivan Kalinin <[email protected]>"]
repository = "https://github.com/broxus/everscale-types"
version = "0.1.0-rc.6"
edition = "2021"
rust-version = "1.65"
rust-version = "1.77"
include = ["src/**/*.rs", "benches/**/*.rs", "LICENSE-*", "README.md"]
license = "MIT OR Apache-2.0"

Expand All @@ -17,6 +17,10 @@ harness = false
name = "dict"
harness = false

[[bench]]
name = "usage_cell"
harness = false

[workspace]
members = ["proc"]

Expand All @@ -27,12 +31,12 @@ base64 = { version = "0.21.0", optional = true }
bitflags = "2.3"
bytes = { version = "1.4", optional = true }
crc32c = "0.6"
dashmap = { version = "5.4", optional = true }
ed25519-dalek = { version = "2.0", optional = true }
everscale-crypto = { version = "0.2", features = ["tl-proto"], optional = true }
hex = "0.4"
num-bigint = { version = "0.4", optional = true }
num-traits = { version = "0.2", optional = true }
once_cell = "1.16"
rand = { version = "0.8", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
sha2 = "0.10"
Expand All @@ -54,7 +58,7 @@ serde_json = "1"

[features]
default = ["base64", "serde", "models", "sync"]
sync = []
sync = ["dep:dashmap"]
stats = []
serde = ["dep:serde", "base64"]
rand = ["dep:rand"]
Expand All @@ -69,6 +73,7 @@ abi = [
"models",
]
venom = []
tycho = []

[profile.release]
debug = true
Expand Down
94 changes: 94 additions & 0 deletions benches/usage_cell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
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);
11 changes: 10 additions & 1 deletion src/boc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! BOC (Bag Of Cells) implementation.

use crate::cell::{Cell, CellBuilder, CellContext, CellFamily, DynCell, Load, Store};
use crate::cell::{Cell, CellBuilder, CellContext, CellFamily, DynCell, HashBytes, Load, Store};

/// BOC decoder implementation.
pub mod de;
Expand Down Expand Up @@ -83,6 +83,14 @@ impl OptionBoc {
pub struct Boc;

impl Boc {
/// Computes a simple SHA256 hash of the data.
#[inline]
pub fn file_hash(data: impl AsRef<[u8]>) -> HashBytes {
use sha2::Digest;

sha2::Sha256::digest(data).into()
}

/// Encodes the specified cell tree as BOC and
/// returns the `base64` encoded bytes as a string.
#[cfg(any(feature = "base64", test))]
Expand Down Expand Up @@ -493,6 +501,7 @@ mod tests {
}

#[cfg(feature = "serde")]
#[allow(unused)]
#[derive(::serde::Serialize)]
struct SerdeWithCellRef<'a> {
cell: &'a DynCell,
Expand Down
9 changes: 3 additions & 6 deletions src/cell/cell_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,13 +755,10 @@ const unsafe fn virtualize_into_next_wrapper<
cell: &T,
) -> &DynCell {
const fn gen_vtable_ptr<
#[cfg(not(feature = "sync"))] T: CellImpl,
#[cfg(feature = "sync")] T: CellImpl + Send + Sync,
#[cfg(not(feature = "sync"))] T: CellImpl + 'static,
#[cfg(feature = "sync")] T: CellImpl + Send + Sync + 'static,
const L: u8,
>() -> *const ()
where
T: 'static,
{
>() -> *const () {
// SAFETY: "fat" pointer consists of two "slim" pointers
let [_, vtable] = unsafe {
std::mem::transmute::<*const dyn CellImpl, [*const (); 2]>(std::ptr::null::<
Expand Down
7 changes: 7 additions & 0 deletions src/cell/cell_impl/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ use crate::util::TryAsMut;
#[repr(transparent)]
pub struct Cell(Rc<DynCell>);

impl Default for Cell {
#[inline]
fn default() -> Self {
Cell::empty_cell()
}
}

impl std::ops::Deref for Cell {
type Target = DynCell;

Expand Down
6 changes: 2 additions & 4 deletions src/cell/cell_impl/sync.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::alloc::Layout;
use std::borrow::Borrow;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
use std::sync::{Arc, OnceLock};

use super::{
EmptyOrdinaryCell, HeaderWithData, LibraryReference, OrdinaryCell, OrdinaryCellHeader,
Expand Down Expand Up @@ -78,9 +78,7 @@ impl CellFamily for Cell {
type EmptyCellContext = EmptyCellContext;

fn empty_cell() -> Cell {
use once_cell::sync::OnceCell;

static EMPTY_CELL: OnceCell<Cell> = OnceCell::new();
static EMPTY_CELL: OnceLock<Cell> = OnceLock::new();
EMPTY_CELL
.get_or_init(|| Cell(Arc::new(EmptyOrdinaryCell)))
.clone()
Expand Down
Loading

0 comments on commit 0823574

Please sign in to comment.