Use Cow to reduce the cost of page cloning during recursive splits
use std::fmt::{self, Debug};
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering::SeqCst;
-use std::sync::Arc;
+use std::sync::{Arc, atomic::{AtomicUsize, Ordering::SeqCst}};
+use std::borrow::Cow;
use pagecache::PagePtr;
@@ -334,12 +333,12 @@ impl Tree {
) {
let mut path2 = path
.iter()
- .map(|&(f, ref p)| (f.clone(), p.clone()))
- .collect::<Vec<(Frag, _)>>();
+ .map(|&(f, ref p)| (Cow::Borrowed(f), p.clone()))
+ .collect::<Vec<(Cow<'_, Frag>, _)>>();
let mut node2 = node.clone();
node2
.apply(&frag, self.config.merge_operator);
- let frag2 = Frag::Base(node2, None);
+ let frag2 = Cow::Owned(Frag::Base(node2, None));
path2.push((frag2, new_cas_key));
self.recursive_split(path2, &guard)?;
}
@@ -444,12 +443,12 @@ impl Tree {
) {
let mut path2 = path
.iter()
- .map(|&(f, ref p)| (f.clone(), p.clone()))
- .collect::<Vec<(Frag, _)>>();
+ .map(|&(f, ref p)| (Cow::Borrowed(f), p.clone()))
+ .collect::<Vec<(Cow<'_, Frag>, _)>>();
let mut node2 = node.clone();
node2
.apply(&frag, self.config.merge_operator);
- let frag2 = Frag::Base(node2, None);
+ let frag2 = Cow::Owned(Frag::Base(node2, None));
path2.push((frag2, new_cas_key));
self.recursive_split(path2, &guard)?;
}
@@ -617,7 +616,7 @@ impl Tree {
fn recursive_split<'g>(
&self,
- path: Vec<(Frag, TreePtr<'g>)>,
+ path: Vec<(Cow<'g, Frag>, TreePtr<'g>)>,
guard: &'g Guard,
) -> Result<(), ()> {
// to split, we pop the path, see if it's in need of split, recurse up
