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

[multiverse RPC]: add better universe root node cache #1169

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

guggero
Copy link
Member

@guggero guggero commented Nov 4, 2024

Fixes #880.

Opening as draft, mainly looking for concept ACK.

@Roasbeef the idea here is the following:

  • Since the universe sync is what needs to be fast, we add a completely new cache for those queries
  • The syncer client always queries with sort=ascending and WithAmountsById=false, which allows us to optimize the new cache and keep all root nodes in memory for those queries
  • The old/existing page based root node cache will only be used for custom user queries that want descending order or WithAmountsById=true, which allows us to keep a much smaller cache
  • All the other caches remain untouched in their functionality (just renamed and made configurable).

TODOs:

  • Test new cache
  • Update comments in RPC proto file that order of results is dependent on query parameters (depending on whether they hit the syncer cache or not).

This commit adds a completely new cache that is tailor made for the
queries the syncer makes (ascending, without any amounts by ID).
This additional cache has all roots (without details), so the existing
cache will only be needed for custom queries that aren't coming from the
syncer.
We should be able to down-size the existing cache quite a bit, as it
should only serve manual requests or requests coming from an UI.

We'll make the size configurable in an upcoming commit.
@guggero guggero requested a review from Roasbeef November 4, 2024 14:57
@coveralls
Copy link

Pull Request Test Coverage Report for Build 11666780661

Details

  • 275 of 568 (48.42%) changed or added relevant lines in 7 files are covered.
  • 36 unchanged lines in 8 files lost coverage.
  • Overall coverage decreased (-0.004%) to 40.721%

Changes Missing Coverage Covered Lines Changed/Added Lines %
chain_bridge.go 0 3 0.0%
tapcfg/config.go 0 3 0.0%
tapcfg/server.go 0 3 0.0%
tapdb/multiverse.go 82 177 46.33%
tapdb/multiverse_cache.go 183 372 49.19%
Files with Coverage Reduction New Missed Lines %
tappsbt/create.go 2 53.22%
tapgarden/planter.go 2 74.87%
tapchannel/aux_leaf_signer.go 3 35.92%
commitment/tap.go 4 84.43%
asset/asset.go 4 81.61%
universe/interface.go 5 50.65%
tapgarden/caretaker.go 8 68.5%
tapdb/multiverse.go 8 60.84%
Totals Coverage Status
Change from base Build 11637218948: -0.004%
Covered Lines: 24733
Relevant Lines: 60737

💛 - Coveralls

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

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

Approach ACK!

// remainder. And the way the cache query is built (query, if not found,
// acquire lock, query again), we always make two queries for each page.
numMisses := ((numAssets / pageSize) + 1) * 2
require.EqualValues(t, 0, multiverse.rootNodeCache.hit.Load())
Copy link
Member

Choose a reason for hiding this comment

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

Nice usage of the internal stat counter here to test the his/misses!

// paging through them. This map never needs to be cleared, as universe
// roots are only added (new issuance or transfer events) or modified
// (re-issuance into grouped asset or new transfer) but never removed.
// Therefore, when the cache needs to be wiped, we only need to clear
Copy link
Member

Choose a reason for hiding this comment

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

but never removed.

It's not exposed over the RPC interface rn, but they can be removed (see the DeleteUniverse method).

return &syncerRootNodeCache{
universeRoots: make(
map[universe.IdentifierKey]universe.Root,
numCachedProofs,
Copy link
Member

Choose a reason for hiding this comment

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

I think we can pre-size this to a larger size, as rn it's set to 50k, but we have ~175k assets on mainnet rn.


// If we have the write lock already, no need to fetch it.
if !haveWriteLock {
r.RLock()
Copy link
Member

Choose a reason for hiding this comment

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

This grabs the read lock, but seems the intention is to grab the write lock.

limit := q.Limit

// Is the page valid?
if offset < 0 || offset >= int32(len(r.universeRoots)) || limit <= 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Log this w/ a warning?

r.universeKeyList = append(r.universeKeyList, root.ID.Key())
r.universeRoots[root.ID.Key()] = root

// To make sue we can easily add and remove entries, we sort the
Copy link
Member

Choose a reason for hiding this comment

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

Can pull into a helper method, as used above verbatim.

//
// NOTE: This method must be called while holding the syncer cache lock.
func (r *syncerRootNodeCache) remove(key universe.IdentifierKey) {
idx := sort.Search(len(r.universeKeyList), func(i int) bool {
Copy link
Member

Choose a reason for hiding this comment

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

Nice usage of sort.Search here 👍

})
if idx < len(r.universeKeyList) && r.universeKeyList[idx] == key {
// Remove the entry from the list.
r.universeKeyList = append(
Copy link
Member

Choose a reason for hiding this comment

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

Can use the slices package here: https://pkg.go.dev/slices#Delete

// caches that exist.
//
//nolint:lll
type MultiverseCacheConfig struct {
Copy link
Member

Choose a reason for hiding this comment

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

👍

// multiverse cache.
func DefaultMultiverseCacheConfig() MultiverseCacheConfig {
return MultiverseCacheConfig{
ProofsPerUniverse: 5,
Copy link
Member

Choose a reason for hiding this comment

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

Temp for this commit?

We should inherit the defaults defined in the existing package here.

@GeorgeTsagk GeorgeTsagk self-requested a review November 5, 2024 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

[bug]: universe_roots cache-hit ratio, gross underperformance
4 participants