Skip to content

Commit be28605

Browse files
authored
refactor: relocate vec types for benchmarks (#336)
This PR refactors the benchmarks to remove the dependency on test types by introducing local copies of `UnboundedVecN` and `BoundedVecN`. Copies of those types allow to run stable-structures version before those types were introduced. This change was tested on stable-structures v0.6.7.
1 parent e710505 commit be28605

File tree

7 files changed

+98
-16
lines changed

7 files changed

+98
-16
lines changed

benchmarks/btreemap/src/main.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use benchmarks::common::Random;
1+
use benchmarks::{random::Random, vec::UnboundedVecN};
22
use canbench_rs::{bench, bench_fn, BenchResult};
33
use ic_stable_structures::memory_manager::{MemoryId, MemoryManager};
4-
use ic_stable_structures::{
5-
storable::{Blob, UnboundedVecN},
6-
BTreeMap, DefaultMemoryImpl, Memory, Storable,
7-
};
4+
use ic_stable_structures::{storable::Blob, BTreeMap, DefaultMemoryImpl, Memory, Storable};
85
use std::ops::Bound;
96
use tiny_rng::{Rand, Rng};
107

benchmarks/compare/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
use benchmarks::vec::BoundedVecN;
12
use canbench_rs::{bench, bench_fn};
23
use ic_cdk::api::stable::WASM_PAGE_SIZE_IN_BYTES;
34
use ic_stable_structures::{
45
memory_manager::{MemoryId, MemoryManager},
5-
storable::BoundedVecN,
66
BTreeMap, DefaultMemoryImpl, Memory, Vec as StableVec,
77
};
88

benchmarks/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
pub mod common;
1+
pub mod random;
2+
pub mod vec;

benchmarks/src/common.rs renamed to benchmarks/src/random.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use ic_stable_structures::storable::{Blob, BoundedVecN, Storable, UnboundedVecN};
1+
use crate::vec::{BoundedVecN, UnboundedVecN};
2+
use ic_stable_structures::storable::{Blob, Storable};
23
use tiny_rng::{Rand, Rng};
34

45
pub trait Random {
@@ -20,7 +21,7 @@ impl<const K: usize> Random for Blob<K> {
2021

2122
impl<const K: usize> Random for UnboundedVecN<K> {
2223
fn random(rng: &mut Rng) -> Self {
23-
let size = rng.rand_u32() % Self::max_size();
24+
let size = rng.rand_u32() % Self::MAX_SIZE;
2425
let mut buf = Vec::with_capacity(size as usize);
2526
for _ in 0..size {
2627
buf.push(rng.rand_u8());

benchmarks/src/vec.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use ic_stable_structures::storable::{Bound, Storable};
2+
use std::borrow::Cow;
3+
4+
/// Unbounded vector of bytes, always of length `N`.
5+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
6+
pub struct UnboundedVecN<const N: usize>(Vec<u8>);
7+
8+
impl<const N: usize> UnboundedVecN<N> {
9+
pub const MAX_SIZE: u32 = N as u32;
10+
11+
pub fn from(slice: &[u8]) -> Self {
12+
assert!(
13+
slice.len() <= N,
14+
"expected a slice with length <= {} bytes, but found {} bytes",
15+
N,
16+
slice.len()
17+
);
18+
let mut vec = Vec::with_capacity(N);
19+
vec.extend_from_slice(slice);
20+
vec.resize(N, 0);
21+
Self(vec)
22+
}
23+
}
24+
25+
impl<const N: usize> Default for UnboundedVecN<N> {
26+
fn default() -> Self {
27+
Self(vec![0; N])
28+
}
29+
}
30+
31+
impl<const N: usize> Storable for UnboundedVecN<N> {
32+
fn to_bytes(&self) -> Cow<[u8]> {
33+
Cow::Owned(self.0.clone())
34+
}
35+
36+
#[inline]
37+
fn from_bytes(bytes: Cow<[u8]>) -> Self {
38+
Self(bytes.into_owned())
39+
}
40+
41+
const BOUND: Bound = Bound::Unbounded;
42+
}
43+
44+
/// Bounded vector of bytes, always of length `N`.
45+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
46+
pub struct BoundedVecN<const N: usize>(Vec<u8>);
47+
48+
impl<const N: usize> BoundedVecN<N> {
49+
pub fn max_size() -> u32 {
50+
N as u32
51+
}
52+
53+
pub fn from(slice: &[u8]) -> Self {
54+
assert!(
55+
slice.len() <= N,
56+
"expected a slice with length <= {} bytes, but found {} bytes",
57+
N,
58+
slice.len()
59+
);
60+
let mut vec = Vec::with_capacity(N);
61+
vec.extend_from_slice(slice);
62+
vec.resize(N, 0);
63+
Self(vec)
64+
}
65+
}
66+
67+
impl<const N: usize> Default for BoundedVecN<N> {
68+
fn default() -> Self {
69+
Self(vec![0; N])
70+
}
71+
}
72+
73+
impl<const N: usize> Storable for BoundedVecN<N> {
74+
fn to_bytes(&self) -> Cow<[u8]> {
75+
Cow::Owned(self.0.clone())
76+
}
77+
78+
#[inline]
79+
fn from_bytes(bytes: Cow<[u8]>) -> Self {
80+
Self(bytes.into_owned())
81+
}
82+
83+
const BOUND: Bound = Bound::Bounded {
84+
max_size: N as u32,
85+
is_fixed_size: false,
86+
};
87+
}

benchmarks/vec/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use benchmarks::common::Random;
1+
use benchmarks::random::Random;
22
use canbench_rs::{bench, bench_fn, BenchResult};
33
use ic_stable_structures::memory_manager::{MemoryId, MemoryManager};
44
use ic_stable_structures::storable::Blob;

src/storable.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,7 @@ impl<const N: usize> Storable for Blob<N> {
195195
pub struct UnboundedVecN<const N: usize>(Vec<u8>);
196196

197197
impl<const N: usize> UnboundedVecN<N> {
198-
pub fn max_size() -> u32 {
199-
N as u32
200-
}
198+
pub const MAX_SIZE: u32 = N as u32;
201199

202200
pub fn from(slice: &[u8]) -> Self {
203201
assert!(
@@ -237,9 +235,7 @@ impl<const N: usize> Storable for UnboundedVecN<N> {
237235
pub struct BoundedVecN<const N: usize>(Vec<u8>);
238236

239237
impl<const N: usize> BoundedVecN<N> {
240-
pub fn max_size() -> u32 {
241-
N as u32
242-
}
238+
pub const MAX_SIZE: u32 = N as u32;
243239

244240
pub fn from(slice: &[u8]) -> Self {
245241
assert!(

0 commit comments

Comments
 (0)