From ccba3158b59c42f49611d7702ffe87bd03099271 Mon Sep 17 00:00:00 2001 From: tiye Date: Tue, 31 May 2022 15:26:38 +0800 Subject: [PATCH] switch back to ref_get for speed in Calcit; tag 0.0.10 --- Cargo.toml | 2 +- src/lib.rs | 9 ++++++--- src/tree.rs | 31 +++++++++++++++---------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c7c955..7a828e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "im_ternary_tree" -version = "0.0.9" +version = "0.0.10" edition = "2021" authors = ["jiyinyiyong "] license = "MIT" diff --git a/src/lib.rs b/src/lib.rs index 12a1ea4..969b604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,11 +63,14 @@ where } /// get element in list by reference + /// PERF: recursive function is slower than iterative loop with Cell in bench(using `usize`), + /// however, Calcit is heavy in cloning(reference though... according real practice), + /// so here we still choose `ref_get` for speed in Calcit project. pub fn get(&self, idx: usize) -> Option<&T> { if self.is_empty() || idx >= self.len() { None } else { - self.loop_get(idx) + self.ref_get(idx) } } @@ -411,7 +414,7 @@ where fn next(&mut self) -> Option { if self.index < self.value.len() { // println!("get: {} {}", self.value.format_inline(), self.index); - let ret = self.value.loop_get(self.index); + let ret = self.value.ref_get(self.index); self.index += 1; ret } else { @@ -467,7 +470,7 @@ where } else { match self { Empty => panic!("list is empty to index"), - Tree(t) => t.loop_get(idx), + Tree(t) => t.ref_get(idx), } } } diff --git a/src/tree.rs b/src/tree.rs index 4e9a0ca..2253d36 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -4,7 +4,7 @@ mod finger; -use std::cell::RefCell; +use std::cell::Cell; use std::cmp::Ordering; use std::fmt; use std::fmt::{Debug, Display}; @@ -213,7 +213,7 @@ where /// internal usages for rebuilding tree fn to_leaves(&self) -> Vec> { let mut acc: Vec> = Vec::with_capacity(self.len()); - let counter: RefCell = RefCell::new(0); + let counter: Cell = Cell::new(0); write_leaves(self, &mut acc, &counter); assert_eq!(acc.len(), self.len()); acc @@ -254,35 +254,34 @@ where /// get am element via drilling down the branch with a mutable loop, /// supposed to be faster than `ref_get` since it's more like VM instructions pub fn loop_get(&'a self, original_idx: usize) -> &'a T { - let r = RefCell::new(self); - let mut tree_parent = r.borrow_mut(); + let tree_parent = Cell::new(self); let mut idx = original_idx; loop { - match *tree_parent { + match tree_parent.get() { Leaf(value) => { - return value; + return &*value; } Branch2 { left, middle, .. } => { if idx < left.len() { - *tree_parent = left; + tree_parent.set(left); } else { - *tree_parent = middle; + tree_parent.set(middle); idx -= left.len(); } } Branch3 { left, middle, right, .. } => { if idx < left.len() { - *tree_parent = left; + tree_parent.set(left); continue; } idx -= left.len(); if idx < middle.len() { - *tree_parent = middle; + tree_parent.set(middle); continue; } - *tree_parent = right; + tree_parent.set(right); idx -= middle.len(); } } @@ -976,7 +975,7 @@ where fn next(&mut self) -> Option { if self.index < self.value.len() { // println!("get: {} {}", self.value.format_inline(), self.index); - let ret = self.value.loop_get(self.index); + let ret = self.value.ref_get(self.index); self.index += 1; Some(ret) } else { @@ -992,7 +991,7 @@ impl Part } for idx in 0..ys.len() { - if self.loop_get(idx) != ys.loop_get(idx) { + if self.ref_get(idx) != ys.ref_get(idx) { return false; } } @@ -1019,7 +1018,7 @@ where fn cmp(&self, other: &Self) -> Ordering { if self.len() == other.len() { for idx in 0..self.len() { - match self.loop_get(idx).cmp(other.loop_get(idx)) { + match self.ref_get(idx).cmp(other.ref_get(idx)) { Ordering::Equal => {} a => return a, } @@ -1040,7 +1039,7 @@ where fn index<'b>(&self, idx: usize) -> &Self::Output { // println!("get: {} {}", self.format_inline(), idx); - self.loop_get(idx) + self.ref_get(idx) } } @@ -1067,7 +1066,7 @@ where } /// internal function for mutable writing -fn write_leaves(xs: &TernaryTree, acc: &mut Vec>, counter: &RefCell) +fn write_leaves(xs: &TernaryTree, acc: &mut Vec>, counter: &Cell) where T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash, {