Merge pull request #6347 from paritytech/trieiter
Optimize trie iter by avoiding redundant copying
This commit is contained in:
commit
5dac15fa85
@ -275,9 +275,15 @@ impl<'a> TrieDBIterator<'a> {
|
|||||||
|
|
||||||
/// Descend into a payload.
|
/// Descend into a payload.
|
||||||
fn descend(&mut self, d: &[u8]) -> super::Result<()> {
|
fn descend(&mut self, d: &[u8]) -> super::Result<()> {
|
||||||
|
let node = Node::decoded(&self.db.get_raw_or_lookup(d)?).into();
|
||||||
|
Ok(self.descend_into_node(node))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Descend into a payload.
|
||||||
|
fn descend_into_node(&mut self, node: OwnedNode) {
|
||||||
self.trail.push(Crumb {
|
self.trail.push(Crumb {
|
||||||
status: Status::Entering,
|
status: Status::Entering,
|
||||||
node: Node::decoded(&self.db.get_raw_or_lookup(d)?).into(),
|
node: node,
|
||||||
});
|
});
|
||||||
match &self.trail.last().expect("just pushed item; qed").node {
|
match &self.trail.last().expect("just pushed item; qed").node {
|
||||||
&OwnedNode::Leaf(ref n, _) | &OwnedNode::Extension(ref n, _) => {
|
&OwnedNode::Leaf(ref n, _) | &OwnedNode::Extension(ref n, _) => {
|
||||||
@ -285,8 +291,6 @@ impl<'a> TrieDBIterator<'a> {
|
|||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The present key.
|
/// The present key.
|
||||||
@ -318,52 +322,67 @@ impl<'a> Iterator for TrieDBIterator<'a> {
|
|||||||
type Item = TrieItem<'a>;
|
type Item = TrieItem<'a>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
enum IterStep {
|
||||||
|
Continue,
|
||||||
|
PopTrail,
|
||||||
|
Descend(super::Result<DBValue>),
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let b = match self.trail.last_mut() {
|
let iter_step = {
|
||||||
Some(mut b) => { b.increment(); b.clone() },
|
match self.trail.last_mut() {
|
||||||
None => return None,
|
Some(b) => { b.increment(); },
|
||||||
|
None => return None,
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = self.trail.last().expect("trail.last_mut().is_some(); qed");
|
||||||
|
|
||||||
|
match (b.status.clone(), &b.node) {
|
||||||
|
(Status::Exiting, n) => {
|
||||||
|
match *n {
|
||||||
|
OwnedNode::Leaf(ref n, _) | OwnedNode::Extension(ref n, _) => {
|
||||||
|
let l = self.key_nibbles.len();
|
||||||
|
self.key_nibbles.truncate(l - n.len());
|
||||||
|
},
|
||||||
|
OwnedNode::Branch(_, _) => { self.key_nibbles.pop(); },
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
IterStep::PopTrail
|
||||||
|
},
|
||||||
|
(Status::At, &OwnedNode::Leaf(_, ref v)) | (Status::At, &OwnedNode::Branch(_, Some(ref v))) => {
|
||||||
|
return Some(Ok((self.key(), v.clone())));
|
||||||
|
},
|
||||||
|
(Status::At, &OwnedNode::Extension(_, ref d)) => IterStep::Descend(self.db.get_raw_or_lookup(&*d)),
|
||||||
|
(Status::At, &OwnedNode::Branch(_, _)) => IterStep::Continue,
|
||||||
|
(Status::AtChild(i), &OwnedNode::Branch(ref children, _)) if children[i].len() > 0 => {
|
||||||
|
match i {
|
||||||
|
0 => self.key_nibbles.push(0),
|
||||||
|
i => *self.key_nibbles.last_mut()
|
||||||
|
.expect("pushed as 0; moves sequentially; removed afterwards; qed") = i as u8,
|
||||||
|
}
|
||||||
|
IterStep::Descend(self.db.get_raw_or_lookup(&*children[i]))
|
||||||
|
},
|
||||||
|
(Status::AtChild(i), &OwnedNode::Branch(_, _)) => {
|
||||||
|
if i == 0 {
|
||||||
|
self.key_nibbles.push(0);
|
||||||
|
}
|
||||||
|
IterStep::Continue
|
||||||
|
},
|
||||||
|
_ => panic!() // Should never see Entering or AtChild without a Branch here.
|
||||||
|
}
|
||||||
};
|
};
|
||||||
match (b.status, b.node) {
|
|
||||||
(Status::Exiting, n) => {
|
match iter_step {
|
||||||
match n {
|
IterStep::PopTrail => {
|
||||||
OwnedNode::Leaf(n, _) | OwnedNode::Extension(n, _) => {
|
|
||||||
let l = self.key_nibbles.len();
|
|
||||||
self.key_nibbles.truncate(l - n.len());
|
|
||||||
},
|
|
||||||
OwnedNode::Branch(_, _) => { self.key_nibbles.pop(); },
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
self.trail.pop();
|
self.trail.pop();
|
||||||
// continue
|
|
||||||
},
|
},
|
||||||
(Status::At, OwnedNode::Leaf(_, v)) | (Status::At, OwnedNode::Branch(_, Some(v))) => {
|
IterStep::Descend(Ok(d)) => {
|
||||||
return Some(Ok((self.key(), v)));
|
self.descend_into_node(Node::decoded(&d).into())
|
||||||
},
|
},
|
||||||
(Status::At, OwnedNode::Extension(_, d)) => {
|
IterStep::Descend(Err(e)) => {
|
||||||
if let Err(e) = self.descend(&*d) {
|
return Some(Err(e))
|
||||||
return Some(Err(e));
|
}
|
||||||
}
|
IterStep::Continue => {},
|
||||||
// continue
|
|
||||||
},
|
|
||||||
(Status::At, OwnedNode::Branch(_, _)) => {},
|
|
||||||
(Status::AtChild(i), OwnedNode::Branch(ref children, _)) if children[i].len() > 0 => {
|
|
||||||
match i {
|
|
||||||
0 => self.key_nibbles.push(0),
|
|
||||||
i => *self.key_nibbles.last_mut()
|
|
||||||
.expect("pushed as 0; moves sequentially; removed afterwards; qed") = i as u8,
|
|
||||||
}
|
|
||||||
if let Err(e) = self.descend(&*children[i]) {
|
|
||||||
return Some(Err(e));
|
|
||||||
}
|
|
||||||
// continue
|
|
||||||
},
|
|
||||||
(Status::AtChild(i), OwnedNode::Branch(_, _)) => {
|
|
||||||
if i == 0 {
|
|
||||||
self.key_nibbles.push(0);
|
|
||||||
}
|
|
||||||
// continue
|
|
||||||
},
|
|
||||||
_ => panic!() // Should never see Entering or AtChild without a Branch here.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user