diff --git a/benchmarks/btreemap/src/main.rs b/benchmarks/btreemap/src/main.rs index c8781e49..bcc78fb0 100644 --- a/benchmarks/btreemap/src/main.rs +++ b/benchmarks/btreemap/src/main.rs @@ -1,10 +1,7 @@ -use benchmarks::common::Random; +use benchmarks::{random::Random, vec::UnboundedVecN}; use canbench_rs::{bench, bench_fn, BenchResult}; use ic_stable_structures::memory_manager::{MemoryId, MemoryManager}; -use ic_stable_structures::{ - storable::{Blob, UnboundedVecN}, - BTreeMap, DefaultMemoryImpl, Memory, Storable, -}; +use ic_stable_structures::{storable::Blob, BTreeMap, DefaultMemoryImpl, Memory, Storable}; use std::ops::Bound; use tiny_rng::{Rand, Rng}; diff --git a/benchmarks/compare/src/main.rs b/benchmarks/compare/src/main.rs index 310a3dc4..196fb544 100644 --- a/benchmarks/compare/src/main.rs +++ b/benchmarks/compare/src/main.rs @@ -1,8 +1,8 @@ +use benchmarks::vec::BoundedVecN; use canbench_rs::{bench, bench_fn}; use ic_cdk::api::stable::WASM_PAGE_SIZE_IN_BYTES; use ic_stable_structures::{ memory_manager::{MemoryId, MemoryManager}, - storable::BoundedVecN, BTreeMap, DefaultMemoryImpl, Memory, Vec as StableVec, }; diff --git a/benchmarks/src/lib.rs b/benchmarks/src/lib.rs index 34994bf5..93ebdd8c 100644 --- a/benchmarks/src/lib.rs +++ b/benchmarks/src/lib.rs @@ -1 +1,2 @@ -pub mod common; +pub mod random; +pub mod vec; diff --git a/benchmarks/src/common.rs b/benchmarks/src/random.rs similarity index 87% rename from benchmarks/src/common.rs rename to benchmarks/src/random.rs index 5e283acd..e5fc08ee 100644 --- a/benchmarks/src/common.rs +++ b/benchmarks/src/random.rs @@ -1,4 +1,5 @@ -use ic_stable_structures::storable::{Blob, BoundedVecN, Storable, UnboundedVecN}; +use crate::vec::{BoundedVecN, UnboundedVecN}; +use ic_stable_structures::storable::{Blob, Storable}; use tiny_rng::{Rand, Rng}; pub trait Random { @@ -20,7 +21,7 @@ impl Random for Blob { impl Random for UnboundedVecN { fn random(rng: &mut Rng) -> Self { - let size = rng.rand_u32() % Self::max_size(); + let size = rng.rand_u32() % Self::MAX_SIZE; let mut buf = Vec::with_capacity(size as usize); for _ in 0..size { buf.push(rng.rand_u8()); diff --git a/benchmarks/src/vec.rs b/benchmarks/src/vec.rs new file mode 100644 index 00000000..4f099af4 --- /dev/null +++ b/benchmarks/src/vec.rs @@ -0,0 +1,87 @@ +use ic_stable_structures::storable::{Bound, Storable}; +use std::borrow::Cow; + +/// Unbounded vector of bytes, always of length `N`. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct UnboundedVecN(Vec); + +impl UnboundedVecN { + pub const MAX_SIZE: u32 = N as u32; + + pub fn from(slice: &[u8]) -> Self { + assert!( + slice.len() <= N, + "expected a slice with length <= {} bytes, but found {} bytes", + N, + slice.len() + ); + let mut vec = Vec::with_capacity(N); + vec.extend_from_slice(slice); + vec.resize(N, 0); + Self(vec) + } +} + +impl Default for UnboundedVecN { + fn default() -> Self { + Self(vec![0; N]) + } +} + +impl Storable for UnboundedVecN { + fn to_bytes(&self) -> Cow<[u8]> { + Cow::Owned(self.0.clone()) + } + + #[inline] + fn from_bytes(bytes: Cow<[u8]>) -> Self { + Self(bytes.into_owned()) + } + + const BOUND: Bound = Bound::Unbounded; +} + +/// Bounded vector of bytes, always of length `N`. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct BoundedVecN(Vec); + +impl BoundedVecN { + pub fn max_size() -> u32 { + N as u32 + } + + pub fn from(slice: &[u8]) -> Self { + assert!( + slice.len() <= N, + "expected a slice with length <= {} bytes, but found {} bytes", + N, + slice.len() + ); + let mut vec = Vec::with_capacity(N); + vec.extend_from_slice(slice); + vec.resize(N, 0); + Self(vec) + } +} + +impl Default for BoundedVecN { + fn default() -> Self { + Self(vec![0; N]) + } +} + +impl Storable for BoundedVecN { + fn to_bytes(&self) -> Cow<[u8]> { + Cow::Owned(self.0.clone()) + } + + #[inline] + fn from_bytes(bytes: Cow<[u8]>) -> Self { + Self(bytes.into_owned()) + } + + const BOUND: Bound = Bound::Bounded { + max_size: N as u32, + is_fixed_size: false, + }; +} diff --git a/benchmarks/vec/src/main.rs b/benchmarks/vec/src/main.rs index 1fda433e..7463ff59 100644 --- a/benchmarks/vec/src/main.rs +++ b/benchmarks/vec/src/main.rs @@ -1,4 +1,4 @@ -use benchmarks::common::Random; +use benchmarks::random::Random; use canbench_rs::{bench, bench_fn, BenchResult}; use ic_stable_structures::memory_manager::{MemoryId, MemoryManager}; use ic_stable_structures::storable::Blob; diff --git a/src/storable.rs b/src/storable.rs index c6a2a8d7..535fe801 100644 --- a/src/storable.rs +++ b/src/storable.rs @@ -195,9 +195,7 @@ impl Storable for Blob { pub struct UnboundedVecN(Vec); impl UnboundedVecN { - pub fn max_size() -> u32 { - N as u32 - } + pub const MAX_SIZE: u32 = N as u32; pub fn from(slice: &[u8]) -> Self { assert!( @@ -237,9 +235,7 @@ impl Storable for UnboundedVecN { pub struct BoundedVecN(Vec); impl BoundedVecN { - pub fn max_size() -> u32 { - N as u32 - } + pub const MAX_SIZE: u32 = N as u32; pub fn from(slice: &[u8]) -> Self { assert!(