Skip to content
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

refactor(pkg/trie/triedb): node level caching #4239

Open
wants to merge 21 commits into
base: development
Choose a base branch
from

Conversation

timwu20
Copy link
Contributor

@timwu20 timwu20 commented Oct 9, 2024

Changes

  • Introduces CachedNode and CachedValue which is used in the TrieCache interface. These are analogous types to codec.EncodedNode and codec.EncodedValue.
  • Adds CachedNodeAccess to the recorder and is recorded accordingly
  • Adds caching functionality to mutable TrieDB functions.
  • Introduces TrieDB.GetHash and triedb.GetWith functions that use TrieLookup with supplied cache.
  • Tests for proper caching functionality

Tests

go test -tags integration github.com/ChainSafe/gossamer

Issues

closes #4157

@timwu20 timwu20 force-pushed the tim/refactor-triedb-caching branch 4 times, most recently from 30419cd to 941f91d Compare October 11, 2024 17:41
@timwu20 timwu20 marked this pull request as ready for review October 11, 2024 18:02
Base automatically changed from tim/refactor-triedb to development October 15, 2024 14:41
@timwu20 timwu20 requested a review from P1sar as a code owner October 15, 2024 19:45
pkg/trie/triedb/nibbles/nibbleslice.go Outdated Show resolved Hide resolved
pkg/trie/triedb/cache.go Outdated Show resolved Hide resolved
Copy link
Member

@EclesioMeloJunior EclesioMeloJunior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, seems solid for me, good work 🚀 !

var depth uint
for {
node, err := cache.GetOrInsertNode(hash, func() (CachedNode[H], error) {
prefixedKey := append(nibbleKey.Mid(keyNibbles).Left().JoinedBytes(), hash.Bytes()...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest a comment here explaining how the prefix key is extracted from the nibbles

for {
// Get node from DB
prefixedKey := append(nibbleKey.Mid(keyNibbles).Left().JoinedBytes(), hash.Bytes()...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest a comment here explaining how the prefix key is extracted from the nibbles

Copy link
Contributor

@dimartiro dimartiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
Just some comments, one specifically regarding the performance of the iterator but it's not a blocker for this PR, we can create an issue and optimize it later if possible

// TODO: we still have some room to improve here, we are caching the raw
// node data and we need to decode it every time we access it. We could
// cache the decoded node instead and avoid decoding it every time.
// This is the same as iterate_all_entries_without_cache since the raw iterator calls TrieDB.getNodeOrLookup
b.Run("iterate_all_entries_with_cache", func(b *testing.B) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the iterator really using the cache? I'm getting the same results for this benchmark with / without the cache

Benchmark_NodesCache/iterate_all_entries_without_cache-12         	   24370	     49277 ns/op	   18688 B/op	    2105 allocs/op
Benchmark_NodesCache/iterate_all_entries_with_cache-12            	   22998	     49445 ns/op	   18688 B/op	    2105 allocs/op

I think you need to use the cache in the triedb.fetchValue method too

@@ -24,7 +24,7 @@ type (
// InlineNode contains bytes of the encoded node data
InlineNode []byte
// HashedNode contains a hash used to lookup in db for encoded node data
HashedNode[H any] struct{ Hash H }
HashedNode[H hash.Hash] struct{ Hash H }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no issues when we are using prefixed keys here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants