-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Iterator refactoring #181
Iterator refactoring #181
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About the PR, removing &db
from Raw/Node iterator looks like a good change to me (no need for the suspended, and surely calling it raw makes it clear one can do something wrong with this iterator).
What are the plans for the substrate optim, I remember planning to use the suspended struct in host function to use it again if the start key used in a following next_key call is the same as the previously return key (but don't find back my branch)?
Or is there an idea to use a host api that keep state of iterator (I got in https://github.com/cheme/substrate/tree/transient a host api that keeps a hasher state in memory could be runing similarily)?
Regarding possible substrate optimization, there is one I would find interesting, that would be to switch sp-state-machine backend
trait to use &mut
on all accesses, thus removing the need for inner mutability (for trie cache and recorder). I started in this direction in paritytech/substrate#13006, but only covered Externalities
trait (switching trie backend requires other changes, at least one existing clone to fetch runtime, but it can certainly be avoided). But I think this would not touch the trie crate (recorder and cache being already &mut).
trie-db/src/iterator.rs
Outdated
&mut self, | ||
db: &TrieDB<L>, | ||
) -> Option< | ||
Result<(NibbleVec, Option<TrieHash<L>>, Rc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this pr (just I was a bit surprise when reading the existing code), but really looks like this function should return Result<(&NibbleVec, Option<TrieHash>, Rc<OwnedNode>), TrieHash, CError>,`, quite some key copy involved here. Probably could also get rid of the Rc.
trie-db/src/iterator.rs
Outdated
Ok((mut prefix, _, node)) => { | ||
let maybe_value = match node.node() { | ||
Node::Leaf(partial, value) => { | ||
prefix.append_partial(partial.right()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this PR either, but the key building should be done on the raw iter key_nibbles
directly.
trie-db/src/triedb.rs
Outdated
} | ||
} | ||
|
||
impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBIterator<'a, 'cache, L> { | ||
/// Position the iterator on the first element with key >= `key` | ||
fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> { | ||
TrieIterator::seek(&mut self.inner, key) | ||
self.raw_iter.seek_prefix(self.db, key).map(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if the function for raw_iter seek_prefix
should be rename (I am maybe the one that give this ~ naming in the first place ). Here it just does a seek key which is what we need, but I had to check the code to be sure it is not the variant that seek a key and then remove nodes from the stack so it limits remaining iteration to the prefix.
wasn't it the case already? |
Does the suspended approach not work (I remember putting something in place but probably drop it at some point, not sure why)? |
For now I'm mostly just simplifying the way we do iteration; e.g. the So it is essentially the suspend approach, it just needs these changes to make it fully possible (not everything was originally exported the first time I tried it IIRC) and simpler. In general for now my main objective is to just simplify and remove dangerous methods (those which return a
Hmm.... is this actually going to affect the performance in a substantial way?
Previously they had their dedicated |
Not sure about perf, actually recorder and cache are already behind a refcell in the trie crate. Would still make sense to me to just plain &mut ptr for read access operation and get rid of as much inner mutability as possible, but that is a different question. |
@cheme Okay, I resurrected the fuzz tests (they didn't compile due to too old version of a dependency in The logic's unchanged and I didn't touch the extra clones. You're right that we should be able to refactor it so that it appends to the |
yes the fuzzer is quite often a bit behind, thanks.
I did check a bit, we probably want to return the key_nibbles after the partial (append the partial on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a trie guru. But codewise looks good
Missed you by a few second, but trie-bench changelog can also be updated (not really important tbh), otherwhise latest changes still looks good. |
Ah, sorry, I didn't realize that one's also released on crates.io. I'll update it. |
This PR simplifies and refactors the iterators in
trie-db
.The changes can be summarized as follows:
TrieDBNodeIterator
-likeTrieDBRawIterator
and made it lifetimeless (instead of storing a&TrieDB
it now takes it as a parameter during the iteration)SuspendedTrieDBKeyIterator
was removed since theTrieDBRawIterator
is a complete replacement for it (with the added bonus that it can be iterated on)TrieDBIterator::next
andTrieDBKeyIterator::next
were renamed and moved intoTrieDBRawIterator
with no changes to the logic (except making them use&TrieDB
passed as a parameter instead of the one stored inself
, and cleaning them up slightly)TrieDBIterator
andTrieDBKeyIterator
now useTrieDBRawIterator
under the hood#[inline]
s were added to make recreating a&TrieDB
on each iteration into a zero-cost operationThis makes further refactoring of storage iterators in
substrate
possible.