Skip to content

Commit

Permalink
Avoid one indirection in KeyFragment and use string interning
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastiencs committed May 17, 2021
1 parent ac73799 commit 00399dd
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 32 deletions.
4 changes: 2 additions & 2 deletions tezos/new_context/src/ffi.rs
Expand Up @@ -354,7 +354,7 @@ ocaml_export! {
.map_err(|err| format!("{:?}", err))
.map(|v| {
v.into_iter()
.map(|(s, tree)| ((*s).clone(), tree))
.map(|(s, tree)| (s.to_string(), tree))
.collect::<Vec<_>>()
});

Expand Down Expand Up @@ -594,7 +594,7 @@ ocaml_export! {
.map_err(|err| format!("{:?}", err))
.map(|v| {
v.into_iter()
.map(|(s, tree)| ((*s).clone(), tree))
.map(|(s, tree)| (s.to_string(), tree))
.collect::<Vec<_>>()
});

Expand Down
4 changes: 2 additions & 2 deletions tezos/new_context/src/hash/mod.rs
Expand Up @@ -423,7 +423,7 @@ mod tests {
entry: RefCell::new(None),
commited: Cell::new(false),
};
dummy_tree.insert(Rc::new("a".to_string()).into(), Rc::new(node));
dummy_tree.insert("a".into(), Rc::new(node));

// hexademical representation of above tree:
//
Expand Down Expand Up @@ -536,7 +536,7 @@ mod tests {
entry: RefCell::new(None),
commited: Cell::new(false),
};
tree = tree.update(Rc::new(binding.name.clone()).into(), Rc::new(node));
tree = tree.update(binding.name.as_str().into(), Rc::new(node));
}

let expected_hash = ContextHash::from_base58_check(&test_case.hash).unwrap();
Expand Down
2 changes: 2 additions & 0 deletions tezos/new_context/src/lib.rs
@@ -1,6 +1,8 @@
// Copyright (c) SimpleStaking and Tezedge Contributors
// SPDX-License-Identifier: MIT

#![feature(hash_set_entry)]

// #![forbid(unsafe_code)]

//! Implementation of the TezEdge context for the Tezos economic protocol
Expand Down
29 changes: 25 additions & 4 deletions tezos/new_context/src/tezedge_context.rs
@@ -1,10 +1,7 @@
// Copyright (c) SimpleStaking and Tezedge Contributors
// SPDX-License-Identifier: MIT

use std::{
cell::{Ref, RefCell},
convert::TryInto,
};
use std::{cell::{Ref, RefCell}, collections::HashSet, convert::TryInto};
use std::{convert::TryFrom, rc::Rc};

use crypto::hash::ContextHash;
Expand Down Expand Up @@ -38,6 +35,7 @@ pub struct PatchContextFunction {}
pub struct TezedgeIndex {
pub repository: Rc<RefCell<ContextKeyValueStore>>,
pub patch_context: Rc<BoxRoot<Option<PatchContextFunction>>>,
pub strings: Rc<RefCell<StringInterner>>,
}

impl TezedgeIndex {
Expand All @@ -49,8 +47,14 @@ impl TezedgeIndex {
Self {
repository,
patch_context,
strings: Default::default(),
}
}

pub fn get_str(&self, s: &str) -> Rc<str> {
let mut strings = self.strings.borrow_mut();
strings.get_str(s)
}
}

impl IndexApi<TezedgeContext> for TezedgeIndex {
Expand Down Expand Up @@ -84,6 +88,23 @@ impl IndexApi<TezedgeContext> for TezedgeIndex {
}
}

#[derive(Default)]
pub struct StringInterner {
strings: HashSet<Rc<str>>
}

impl StringInterner {
fn get_str(&mut self, s: &str) -> Rc<str> {
if s.len() >= 30 {
return Rc::from(s);
}

self.strings.get_or_insert_with(s, |s| {
Rc::from(s)
}).clone()
}
}

// context implementation using merkle-tree-like storage
#[derive(Clone)]
pub struct TezedgeContext {
Expand Down
46 changes: 38 additions & 8 deletions tezos/new_context/src/working_tree/mod.rs
Expand Up @@ -12,34 +12,46 @@ use serde::{Deserialize, Serialize};
use crate::hash::{hash_entry, EntryHash, HashingError};
use crate::ContextValue;

use self::working_tree::MerkleError;

pub mod working_tree;
pub mod working_tree_stats;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize)]
pub struct KeyFragment(Rc<String>);
pub struct KeyFragment(Rc<str>);

impl std::ops::Deref for KeyFragment {
type Target = String;
type Target = str;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl KeyFragment {
pub(crate) fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}

pub(crate) fn to_string(&self) -> String {
self.0.to_string()
}
}

impl Borrow<str> for KeyFragment {
fn borrow(&self) -> &str {
self.0.as_str()
&self.0
}
}

impl Borrow<String> for KeyFragment {
fn borrow(&self) -> &String {
&self.0
impl From<&str> for KeyFragment {
fn from(value: &str) -> Self {
KeyFragment(Rc::from(value))
}
}

impl From<Rc<String>> for KeyFragment {
fn from(value: Rc<String>) -> Self {
impl From<Rc<str>> for KeyFragment {
fn from(value: Rc<str>) -> Self {
KeyFragment(value)
}
}
Expand Down Expand Up @@ -116,6 +128,24 @@ impl Node {
}
}
}

pub fn get_hash(&self) -> Result<EntryHash, MerkleError> {
self.entry_hash
.try_borrow()
.map_err(|_| MerkleError::InvalidState("The Entry hash is borrowed more than once"))?
.as_ref()
.copied()
.ok_or(MerkleError::InvalidState("Missing entry hash"))
}

fn set_entry(&self, entry: &Entry) -> Result<(), MerkleError> {
self.entry
.try_borrow_mut()
.map_err(|_| MerkleError::InvalidState("The Entry is borrowed more than once"))?
.replace(entry.clone());

Ok(())
}
}

// Make sure the node contains the entry hash when serializing
Expand Down
46 changes: 30 additions & 16 deletions tezos/new_context/src/working_tree/working_tree.rs
Expand Up @@ -692,7 +692,10 @@ impl WorkingTree {

match new_node {
None => tree.remove(last),
Some(new_node) => tree.insert(Rc::new(last.to_string()).into(), Rc::new(new_node)),
Some(new_node) => {
let last = self.index.get_str(last);
tree.insert(last.into(), Rc::new(new_node))
},
};

if tree.is_empty() {
Expand Down Expand Up @@ -726,8 +729,30 @@ impl WorkingTree {
}
};

// get entry by hash (from working tree or DB)
match self.get_entry(&child_node)? {
// get entry (from working tree)
if let Ok(entry) = child_node.entry.try_borrow() {
match &*entry {
Some(Entry::Tree(tree)) => {
return self.find_raw_tree(tree, &key[1..]);
}
Some(Entry::Blob(_)) => return Ok(Tree::new()),
Some(Entry::Commit { .. }) => {
return Err(MerkleError::FoundUnexpectedStructure {
sought: "Tree/Blob".to_string(),
found: "commit".to_string(),
})
}
None => {}
}
drop(entry);
}

// get entry by hash (from DB)
let hash = child_node.get_hash()?;
let entry = self.get_entry_from_hash(&hash)?;
child_node.set_entry(&entry)?;

match entry {
Entry::Tree(tree) => self.find_raw_tree(&tree, &key[1..]),
Entry::Blob(_) => Ok(Tree::new()),
Entry::Commit { .. } => Err(MerkleError::FoundUnexpectedStructure {
Expand Down Expand Up @@ -841,20 +866,9 @@ impl WorkingTree {
return Ok(e);
};

let hash = node
.entry_hash
.try_borrow()
.map_err(|_| MerkleError::InvalidState("The Entry hash is borrowed more than once"))?
.as_ref()
.copied()
.ok_or(MerkleError::InvalidState("Missing entry hash"))?;

let hash = node.get_hash()?;
let entry = self.get_entry_from_hash(&hash)?;

node.entry
.try_borrow_mut()
.map_err(|_| MerkleError::InvalidState("The Entry is borrowed more than once"))?
.replace(entry.clone());
node.set_entry(&entry)?;

Ok(entry)
}
Expand Down

0 comments on commit 00399dd

Please sign in to comment.