-
Notifications
You must be signed in to change notification settings - Fork 20.4k
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
trie: enable batch updates #24556
trie: enable batch updates #24556
Conversation
I think it's worthwhile for experiment. Not only the For |
And also the Semantically, all the operations in trie right now will always create a copy, apply the mutations(e.g. add the hash flag, replace the hashNode with a resolved node, etc) and eventually replace to root node, this procedure is treated as "atomic". The only concurrency issue will happen at "root" node. We can explore to change the semantics. For example, when the root is resolved from the disk by Get, we can directly link it with its parent without changing all the ancestor nodes. The concurrency happens at this particular node instead of root node. |
Just one thing I'd like to point out... So right now, the range prover seems like it shaves off ~50% on a 10K slice of leafs. However, we could do it even better. Currently, we
This method will always require a moderately large trie (~15-20k nodes) balooning up during the verification, regardless of how much we improve the trie. The alternative way to do this is to
This method will have around 50-100 nodes at any time, and the pool makes it close to alloc-free. So it's intrinsically much better. |
You mean we will always have that many nodes in memory during the verification? If so, yes. But most of them are created in runtime, not resolved from the disk |
I have now updated this PR, and modified it so that it does not touch the core state transition functions, but is only used when verifying range proof. For a somewhat large range, it shaves off 50% of allocations, and 30-50% of the time. Specifically this case as mentioned in the original description:
|
This probably adds more complexity than is warranted. |
A long time ago, I did an experiment (here) with using the trie in a mode where it didn't always copy-on-change. That way of using the trie is unsafe from a concurrency perspective, but in many situations, that's fine.
In the end, I didn't push that feature, I found that it didn't make a lot of difference since most of the time spent during the intermediate root wasn't related to gc, rather disk IO.
However, when we verify proofs (that are large enough that the full trie contents do not fit into a snap response), then the proof verifier uses a trie, shoves in the left and right side bounds, and fills it with e.g. ~10K values, to obtain the trie root. In this case, the batched mode could make a pretty significant change.
So I cherry-picked and tested:
Note: this PR contains some changes to
statedb
, which comes from previous experiment. Those changes would need to be checked if they're (still) ok.