Skip to content

Commit ccba315

Browse files
committed
switch back to ref_get for speed in Calcit; tag 0.0.10
1 parent 1ba22f2 commit ccba315

File tree

3 files changed

+22
-20
lines changed

3 files changed

+22
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
[package]
33
name = "im_ternary_tree"
4-
version = "0.0.9"
4+
version = "0.0.10"
55
edition = "2021"
66
authors = ["jiyinyiyong <jiyinyiyong@gmail.com>"]
77
license = "MIT"

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,14 @@ where
6363
}
6464

6565
/// get element in list by reference
66+
/// PERF: recursive function is slower than iterative loop with Cell in bench(using `usize`),
67+
/// however, Calcit is heavy in cloning(reference though... according real practice),
68+
/// so here we still choose `ref_get` for speed in Calcit project.
6669
pub fn get(&self, idx: usize) -> Option<&T> {
6770
if self.is_empty() || idx >= self.len() {
6871
None
6972
} else {
70-
self.loop_get(idx)
73+
self.ref_get(idx)
7174
}
7275
}
7376

@@ -411,7 +414,7 @@ where
411414
fn next(&mut self) -> Option<Self::Item> {
412415
if self.index < self.value.len() {
413416
// println!("get: {} {}", self.value.format_inline(), self.index);
414-
let ret = self.value.loop_get(self.index);
417+
let ret = self.value.ref_get(self.index);
415418
self.index += 1;
416419
ret
417420
} else {
@@ -467,7 +470,7 @@ where
467470
} else {
468471
match self {
469472
Empty => panic!("list is empty to index"),
470-
Tree(t) => t.loop_get(idx),
473+
Tree(t) => t.ref_get(idx),
471474
}
472475
}
473476
}

src/tree.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
mod finger;
66

7-
use std::cell::RefCell;
7+
use std::cell::Cell;
88
use std::cmp::Ordering;
99
use std::fmt;
1010
use std::fmt::{Debug, Display};
@@ -213,7 +213,7 @@ where
213213
/// internal usages for rebuilding tree
214214
fn to_leaves(&self) -> Vec<TernaryTree<T>> {
215215
let mut acc: Vec<TernaryTree<T>> = Vec::with_capacity(self.len());
216-
let counter: RefCell<usize> = RefCell::new(0);
216+
let counter: Cell<usize> = Cell::new(0);
217217
write_leaves(self, &mut acc, &counter);
218218
assert_eq!(acc.len(), self.len());
219219
acc
@@ -254,35 +254,34 @@ where
254254
/// get am element via drilling down the branch with a mutable loop,
255255
/// supposed to be faster than `ref_get` since it's more like VM instructions
256256
pub fn loop_get(&'a self, original_idx: usize) -> &'a T {
257-
let r = RefCell::new(self);
258-
let mut tree_parent = r.borrow_mut();
257+
let tree_parent = Cell::new(self);
259258
let mut idx = original_idx;
260259
loop {
261-
match *tree_parent {
260+
match tree_parent.get() {
262261
Leaf(value) => {
263-
return value;
262+
return &*value;
264263
}
265264
Branch2 { left, middle, .. } => {
266265
if idx < left.len() {
267-
*tree_parent = left;
266+
tree_parent.set(left);
268267
} else {
269-
*tree_parent = middle;
268+
tree_parent.set(middle);
270269
idx -= left.len();
271270
}
272271
}
273272
Branch3 { left, middle, right, .. } => {
274273
if idx < left.len() {
275-
*tree_parent = left;
274+
tree_parent.set(left);
276275
continue;
277276
}
278277
idx -= left.len();
279278

280279
if idx < middle.len() {
281-
*tree_parent = middle;
280+
tree_parent.set(middle);
282281
continue;
283282
}
284283

285-
*tree_parent = right;
284+
tree_parent.set(right);
286285
idx -= middle.len();
287286
}
288287
}
@@ -976,7 +975,7 @@ where
976975
fn next(&mut self) -> Option<Self::Item> {
977976
if self.index < self.value.len() {
978977
// println!("get: {} {}", self.value.format_inline(), self.index);
979-
let ret = self.value.loop_get(self.index);
978+
let ret = self.value.ref_get(self.index);
980979
self.index += 1;
981980
Some(ret)
982981
} else {
@@ -992,7 +991,7 @@ impl<T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash> Part
992991
}
993992

994993
for idx in 0..ys.len() {
995-
if self.loop_get(idx) != ys.loop_get(idx) {
994+
if self.ref_get(idx) != ys.ref_get(idx) {
996995
return false;
997996
}
998997
}
@@ -1019,7 +1018,7 @@ where
10191018
fn cmp(&self, other: &Self) -> Ordering {
10201019
if self.len() == other.len() {
10211020
for idx in 0..self.len() {
1022-
match self.loop_get(idx).cmp(other.loop_get(idx)) {
1021+
match self.ref_get(idx).cmp(other.ref_get(idx)) {
10231022
Ordering::Equal => {}
10241023
a => return a,
10251024
}
@@ -1040,7 +1039,7 @@ where
10401039

10411040
fn index<'b>(&self, idx: usize) -> &Self::Output {
10421041
// println!("get: {} {}", self.format_inline(), idx);
1043-
self.loop_get(idx)
1042+
self.ref_get(idx)
10441043
}
10451044
}
10461045

@@ -1067,7 +1066,7 @@ where
10671066
}
10681067

10691068
/// internal function for mutable writing
1070-
fn write_leaves<T>(xs: &TernaryTree<T>, acc: &mut Vec<TernaryTree<T>>, counter: &RefCell<usize>)
1069+
fn write_leaves<T>(xs: &TernaryTree<T>, acc: &mut Vec<TernaryTree<T>>, counter: &Cell<usize>)
10711070
where
10721071
T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash,
10731072
{

0 commit comments

Comments
 (0)