Skip to content

perf: add BTreeMap node cache #272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 78 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
0693478
add node cache
maksymar Mar 28, 2025
c03f790
save_header
maksymar Apr 3, 2025
21cedda
save_node
maksymar Apr 3, 2025
a3f03a4
save_node
maksymar Apr 3, 2025
ff73de7
deallocate_node
maksymar Apr 3, 2025
554d8c9
.
maksymar Apr 3, 2025
ef00234
&
maksymar Apr 3, 2025
b1dee01
N=1k
maksymar Apr 3, 2025
e11a373
N=1k
maksymar Apr 3, 2025
aad2d94
dbg
maksymar Apr 3, 2025
07dadb2
.
maksymar Apr 3, 2025
7252ec4
validate
maksymar Apr 3, 2025
930e54e
dbg
maksymar Apr 3, 2025
69824d7
.
maksymar Apr 3, 2025
b09fa99
debug
maksymar Apr 3, 2025
ed5b8b3
debug print
maksymar Apr 3, 2025
d8cfa7f
.gitignore
maksymar Apr 3, 2025
04fc03c
cache in merge
maksymar Apr 3, 2025
c08caa3
.
maksymar Apr 3, 2025
662ab2d
comment debug print
maksymar Apr 3, 2025
796eb9e
.
maksymar Apr 3, 2025
d7ae7c8
.
maksymar Apr 3, 2025
2608ae9
capacity=0
maksymar Apr 3, 2025
f30ed2d
.
maksymar Apr 3, 2025
56100ae
.
maksymar Apr 3, 2025
70e75c0
swap_entry
maksymar Apr 3, 2025
5669e3c
write_node on load_node only
maksymar Apr 3, 2025
909c011
clippy
maksymar Apr 3, 2025
2524bff
cache 1k
maksymar Apr 3, 2025
131ce12
rm validate
maksymar Apr 3, 2025
9258057
.
maksymar Apr 3, 2025
84b10e1
cleanup
maksymar Apr 3, 2025
4d9a32a
rm swap_entry
maksymar Apr 3, 2025
0ca3a90
load_cached_node
maksymar Apr 3, 2025
20688cb
.
maksymar Apr 3, 2025
ffd9094
.
maksymar Apr 3, 2025
430810b
cache size 0
maksymar Apr 3, 2025
76740a5
add NodeCache stats
maksymar Apr 3, 2025
d052efe
NODE_CACHE_SIZE 0
maksymar Apr 3, 2025
8b98669
add debug print instruciton consumption
maksymar Apr 4, 2025
3f113b0
cleanup
maksymar Apr 4, 2025
52e97f9
add stats
maksymar Apr 4, 2025
06cefc8
.
maksymar Apr 4, 2025
bebbc5e
NODE_CACHE_SIZE 1k
maksymar Apr 4, 2025
3fd3f1e
no op on capacity 0
maksymar Apr 4, 2025
ca56192
fix build
maksymar Apr 4, 2025
0aafad8
write_node &
maksymar Apr 4, 2025
7aa8c15
cleanup
maksymar Apr 4, 2025
b8d7ab0
cleanup
maksymar Apr 4, 2025
65cac75
cleanup
maksymar Apr 4, 2025
c227e0e
turn off debug
maksymar Apr 4, 2025
9820ad4
.
maksymar Apr 4, 2025
2b0262c
cleanup
maksymar Apr 4, 2025
2a4fcf3
.
maksymar Apr 4, 2025
6c838fc
rm debug code
maksymar Apr 4, 2025
31cc1be
.
maksymar Apr 4, 2025
dbdca4c
fix feature
maksymar Apr 4, 2025
cc5be19
.
maksymar Apr 4, 2025
68ee50b
minimize storing keys in cache
maksymar Apr 4, 2025
6b59e62
rm K dedupe
maksymar Apr 4, 2025
33657bc
add byte_size limit
maksymar Apr 4, 2025
d0281f5
mv RefCell
maksymar Apr 5, 2025
fd7e463
cleanup
maksymar Apr 5, 2025
1c6b611
cleanup, fixes
maksymar Apr 5, 2025
e36a87e
add tests
maksymar Apr 5, 2025
ff73ddd
test_cache_size_tracking
maksymar Apr 5, 2025
a471071
cleanup tests
maksymar Apr 5, 2025
266935f
entry size 3k+v
maksymar Apr 5, 2025
a19c68d
cleanup
maksymar Apr 5, 2025
c1d7c6a
entry_overhead = 3k+v+2c
maksymar Apr 5, 2025
7bfabde
.
maksymar Apr 5, 2025
333f877
with_size_limit
maksymar Apr 5, 2025
df1e8d2
add more btreemap_get_blob benchmarks
maksymar Apr 7, 2025
86efaa2
update canbench_results
maksymar Apr 7, 2025
b545606
cleanup
maksymar Apr 7, 2025
f7d1a55
10k + debug
maksymar Apr 7, 2025
fd99bf6
0 capacity
maksymar Apr 7, 2025
1e15f7d
merge main
maksymar Apr 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
.vscode/
.idea/
**/*~

tmp/
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ version = "0.6.8"
ic_principal = { version = "0.1.1", default-features = false }
# An optional dependency to benchmark parts of the code.
canbench-rs = { version = "0.1.7", optional = true }
ic-cdk.workspace = true

[dev-dependencies]
candid.workspace = true
hex = "0.4.3"
ic-cdk.workspace = true
ic-cdk-macros.workspace = true
maplit = "1.0.2"
proptest = "1"
Expand Down
44 changes: 37 additions & 7 deletions src/btreemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@
//! ----------------------------------------
//! ```
mod allocator;
pub(crate) mod cache;
mod iter;
mod node;
use crate::btreemap::iter::{IterInternal, KeysIter, ValuesIter};

use crate::btreemap::{
cache::Cache,
iter::{IterInternal, KeysIter, ValuesIter},
};
use crate::{
storable::Bound as StorableBound,
types::{Address, NULL},
Expand All @@ -61,6 +66,7 @@ use allocator::Allocator;
pub use iter::Iter;
use node::{DerivedPageSize, Entry, Node, NodeType, PageSize, Version};
use std::borrow::Cow;
use std::cell::RefCell;
use std::marker::PhantomData;
use std::ops::{Bound, RangeBounds};

Expand Down Expand Up @@ -105,6 +111,9 @@ where

// A marker to communicate to the Rust compiler that we own these types.
_phantom: PhantomData<(K, V)>,

// A cache for storing recently accessed nodes.
node_cache: RefCell<Cache<Address, Node<K>>>,
}

#[derive(PartialEq, Debug)]
Expand Down Expand Up @@ -214,6 +223,7 @@ where
version: Version::V2(page_size),
length: 0,
_phantom: PhantomData,
node_cache: RefCell::new(Cache::new()),
};

btree.save_header();
Expand Down Expand Up @@ -241,6 +251,7 @@ where
}),
length: 0,
_phantom: PhantomData,
node_cache: RefCell::new(Cache::new()),
};

btree.save_header();
Expand Down Expand Up @@ -290,6 +301,7 @@ where
version,
length: header.length,
_phantom: PhantomData,
node_cache: RefCell::new(Cache::new()),
}
}

Expand Down Expand Up @@ -572,6 +584,7 @@ where
self.length = 0;
self.allocator.clear();
self.save_header();
self.node_cache.borrow_mut().clear();
}

/// Returns the first key-value pair in the map. The key in this
Expand Down Expand Up @@ -1081,6 +1094,9 @@ where
/// [1, 2, 3, 4, 5, 6, 7] (stored in the `into` node)
/// `source` is deallocated.
fn merge(&mut self, source: Node<K>, mut into: Node<K>, median: Entry<K>) -> Node<K> {
let mut node_cache = self.node_cache.borrow_mut();
node_cache.remove(&source.address());
node_cache.remove(&into.address());
into.merge(source, median, &mut self.allocator);
into
}
Expand All @@ -1093,21 +1109,35 @@ where
}
}

/// Deallocates a node.
#[inline]
fn deallocate_node(&mut self, node: Node<K>) {
self.node_cache.borrow_mut().remove(&node.address());
node.deallocate(self.allocator_mut());
}

/// Loads a node from memory.
#[inline]
fn load_node(&self, address: Address) -> Node<K> {
Node::load(address, self.version.page_size(), self.memory())

// TODO: debug if this brings any performance improvement.
// self.node_cache.get(address).unwrap_or_else(|| {
// let node = Node::load(address, self.version.page_size(), self.memory());
// self.node_cache.insert(address, &node);
// node
// })
}

fn load_cached_node(&self, address: Address) -> Node<K> {
let mut node_cache = self.node_cache.borrow_mut();
node_cache.get(&address).unwrap_or_else(|| {
let node = Node::load(address, self.version.page_size(), self.memory());
if node_cache.capacity() > 0 {
node_cache.insert(address, node.clone());
}
node
})
}

/// Saves the node to memory.
#[inline]
fn save_node(&mut self, node: &mut Node<K>) {
self.node_cache.borrow_mut().remove(&node.address());
node.save(self.allocator_mut());
}

Expand Down
Loading
Loading