feat: cache Node hash

This commit is contained in:
nazeh
2023-12-29 19:27:59 +03:00
parent 396242bc75
commit 72893db180
4 changed files with 30 additions and 18 deletions

View File

@@ -6,7 +6,6 @@ use crate::{Hash, Hasher, HASH_LEN};
// TODO: room for improvement (pending actual benchmarks to justify):
// - cache encoding
// - cache hashing
// TODO: remove unwrap
// TODO: KeyType and ValueType
@@ -24,6 +23,10 @@ pub struct Node {
// Metadata that should not be encoded.
ref_count: u64,
// Memoized hashes
/// The Hash of the node, if None then something changed, and the hash should be recomputed.
hash: Option<Hash>,
}
#[derive(Debug)]
@@ -47,6 +50,7 @@ impl Node {
right: None,
ref_count: 0,
hash: None,
}
}
@@ -95,9 +99,13 @@ impl Node {
}
/// Returns the hash of the node.
pub fn hash(&self) -> Hash {
let encoded = self.canonical_encode();
hash(&encoded)
pub fn hash(&mut self) -> Hash {
self.hash.unwrap_or_else(|| {
let encoded = self.canonical_encode();
let hash = hash(&encoded);
self.hash = Some(hash);
hash
})
}
// === Private Methods ===
@@ -105,6 +113,8 @@ impl Node {
/// Set the value.
pub(crate) fn set_value(&mut self, value: &[u8]) -> &mut Self {
self.value = value.into();
self.hash = None;
self
}
@@ -124,6 +134,7 @@ impl Node {
Branch::Left => self.left = new_child,
Branch::Right => self.right = new_child,
};
self.hash = None;
self
}
@@ -250,5 +261,6 @@ fn decode_node(data: (u64, &[u8])) -> Node {
right,
ref_count,
hash: None,
}
}

View File

@@ -26,8 +26,8 @@ pub(crate) fn remove<'a>(
node.decrement_ref_count().save(nodes_table);
match branch {
Branch::Left => node.set_left_child(root.map(|n| n.hash())),
Branch::Right => node.set_right_child(root.map(|n| n.hash())),
Branch::Left => node.set_left_child(root.map(|mut n| n.hash())),
Branch::Right => node.set_right_child(root.map(|mut n| n.hash())),
};
node.increment_ref_count().save(nodes_table);
@@ -107,7 +107,7 @@ fn zip_up(
.decrement_ref_count()
.save(nodes_table)
// save new version
.set_left_child(previous.map(|n| n.hash()))
.set_left_child(previous.map(|mut n| n.hash()))
.increment_ref_count()
.save(nodes_table);
@@ -127,7 +127,7 @@ fn zip_up(
.decrement_ref_count()
.save(nodes_table)
// save new version
.set_right_child(previous.map(|n| n.hash()))
.set_right_child(previous.map(|mut n| n.hash()))
.increment_ref_count()
.save(nodes_table);

View File

@@ -150,7 +150,7 @@ fn verify_children_rank(treap: &HashTreap, node: Option<Node>) -> bool {
fn assert_root(treap: &HashTreap, expected_root_hash: &str) {
let root_hash = treap
.root()
.map(|n| n.hash())
.map(|mut n| n.hash())
.expect("Has root hash after insertion");
assert_eq!(
@@ -167,8 +167,8 @@ fn into_mermaid_graph(treap: &HashTreap) -> String {
graph.push_str("graph TD;\n");
if let Some(root) = treap.root() {
build_graph_string(&treap, &root, &mut graph);
if let Some(mut root) = treap.root() {
build_graph_string(&treap, &mut root, &mut graph);
}
graph.push_str(&format!(
@@ -178,28 +178,28 @@ fn into_mermaid_graph(treap: &HashTreap) -> String {
graph
}
fn build_graph_string(treap: &HashTreap, node: &Node, graph: &mut String) {
fn build_graph_string(treap: &HashTreap, node: &mut Node, graph: &mut String) {
let key = format_key(node.key());
let node_label = format!("{}(({}))", node.hash(), key);
// graph.push_str(&format!("## START node {}\n", node_label));
if let Some(child) = treap.get_node(node.left()) {
if let Some(mut child) = treap.get_node(node.left()) {
let key = format_key(child.key());
let child_label = format!("{}(({}))", child.hash(), key);
graph.push_str(&format!(" {} --l--> {};\n", node_label, child_label));
build_graph_string(&treap, &child, graph);
build_graph_string(&treap, &mut child, graph);
} else {
graph.push_str(&format!(" {} -.-> {}l((l));\n", node_label, node.hash()));
graph.push_str(&format!(" class {}l null;\n", node.hash()));
}
if let Some(child) = treap.get_node(node.right()) {
if let Some(mut child) = treap.get_node(node.right()) {
let key = format_key(child.key());
let child_label = format!("{}(({}))", child.hash(), key);
graph.push_str(&format!(" {} --r--> {};\n", node_label, child_label));
build_graph_string(&treap, &child, graph);
build_graph_string(&treap, &mut child, graph);
} else {
graph.push_str(&format!(" {} -.-> {}r((r));\n", node_label, node.hash()));
graph.push_str(&format!(" class {}r null;\n", node.hash()));

View File

@@ -68,7 +68,7 @@ impl<'treap> HashTreap<'treap> {
.root_hash_inner(&roots_table)
.and_then(|hash| Node::open(&nodes_table, hash));
let new_root = crate::operations::insert(&mut nodes_table, old_root, key, value);
let mut new_root = crate::operations::insert(&mut nodes_table, old_root, key, value);
roots_table
.insert(self.name.as_bytes(), new_root.hash().as_bytes().as_slice())
@@ -96,7 +96,7 @@ impl<'treap> HashTreap<'treap> {
removed_node = old_node;
if let Some(new_root) = new_root {
if let Some(mut new_root) = new_root {
roots_table
.insert(self.name.as_bytes(), new_root.hash().as_bytes().as_slice())
.unwrap();