Replies: 4 comments 1 reply
-
Second implementation sounds better in the context of the trie being already in memory .
Encoding node from its in memory value should be faster than reading from db (not if cached).
If by merkle value we are talking about merkle hash, those are not very needed at a single node level. But when considering a whole state, it is very important to have them I mean the sibling hashes of the updated nodes (without them how to calculate new trie root without recalculating hash of all the nodes). |
Beta Was this translation helpful? Give feedback.
-
As an aside.. We know dense tries handle Merkle proofs poorly. Afaik the correct solution is radix-2 hashing, with perhaps radix 16 cashing or whatever. This saves 4x the space on Merkle proofs in dense tries. We'd pay some cost in sparse tries for radix 2 hashing, but this can be fixed by using a hash function with a metadata field that permits "fast forwarding" over null copath elements, so morally the radix 2 hash function looks like
We'd obviously implement |
Beta Was this translation helpful? Give feedback.
-
@cheme Would you mind please let me know a bit more when you flush the write changes to database? I guess you don't write to database trie changes on every key-value pair insertion since AFAIK it's too CPU expensive to scale encode each node in the trie path to the node inserted, right?
|
Beta Was this translation helpful? Give feedback.
-
Sure. Note that technically the new trie nodes are cached on every call to |
Beta Was this translation helpful? Give feedback.
-
I'm currently working on the alternate Go implementation of the Polkadot host, more specifically
on the v1 state trie code and offloading the in-memory trie data to a database (our memory usage is too high since we keep all trie nodes fully in memory).
The following is about storing/loading trie nodes from database in the in-memory trie.
I am suggesting an alternate implementation, and would like to hear your thoughts on it, as well as any critic on my understanding of how Substrate currently works. This is not necessarily something to adopt in Substrate, but it's been on my mind for our Go implementation. I also focus on fat nodes (my own wording) which are trie nodes with an encoding and subvalue both larger than 32 bytes.
Substrate implementation
Writing a key value in the trie
So for fat nodes, it's
1
encoding +2
hashes +2
database writes.Read a key value from the trie
So for 'fat nodes', it's
1
decoding +2
database reads.Suggested alternate implementation
Writing a key value in the trie
So for 'fat nodes', it's
1
hash +1
database write.But each node uses
2
more bytes.The boolean could also be the last bit of the variant byte, so that could be optimized to be
1
more byte only. For example:0100 0001
=> leaf with 32B hashed subvalue0100 0000
=> leaf with 32B inlined subvalueRead a key value from the trie
Here it's
1
database read.Other considerations
Sum up table
1
encoding +2
hashes +2
database writes1
hash +1
database write1
decoding +2
database reads1
database readThank you all!
Beta Was this translation helpful? Give feedback.
All reactions