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

Implement beacon db pruner #14687

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open

Implement beacon db pruner #14687

wants to merge 20 commits into from

Conversation

dB2510
Copy link
Contributor

@dB2510 dB2510 commented Dec 2, 2024

What type of PR is this?
Feature

What does this PR do? Why is it needed?
This PR implements beacon db pruning based on weak subjectivity period. This is needed to avoid storing historical blocks beyond a point for non-archival nodes.

Which issues(s) does this PR fix?
#8787

Other notes for review
This PR implements a pruner service based on weak subjectivity period to periodically delete blocks and states beyond weak subjectivity period to maintain a constant-size database.

Acknowledgements

  • I have read CONTRIBUTING.md.
  • I have made an appropriate entry to CHANGELOG.md.
  • I have added a description to this PR with sufficient context for reviewers to understand this PR.

Copy link
Member

@prestonvanloon prestonvanloon left a comment

Choose a reason for hiding this comment

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

Just one comment on the interface name.

The implementation looks good to me. Do you plan to plug it in with a feature flag in a follow up PR? Have you tested this?

beacon-chain/db/iface/interface.go Outdated Show resolved Hide resolved
@rkapka
Copy link
Contributor

rkapka commented Dec 13, 2024

No flag to customize the retention period?

@dB2510
Copy link
Contributor Author

dB2510 commented Dec 16, 2024

@rkapka

No flag to customize the retention period?

Will include it in this PR.

@dB2510 dB2510 changed the title Implement weak subjectivity pruner Implement beacon db pruner Dec 23, 2024
@dB2510 dB2510 marked this pull request as ready for review December 24, 2024 10:45
@dB2510 dB2510 requested a review from a team as a code owner December 24, 2024 10:45
cmd/beacon-chain/flags/base.go Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
@@ -590,26 +636,26 @@ func (s *Store) SaveRegistrationsByValidatorIDs(ctx context.Context, ids []primi
}

// blockRootsByFilter retrieves the block roots given the filter criteria.
func blockRootsByFilter(ctx context.Context, tx *bolt.Tx, f *filters.QueryFilter) ([][]byte, error) {
func blockRootsByFilter(ctx context.Context, tx *bolt.Tx, f *filters.QueryFilter) ([][]byte, map[primitives.Slot][][]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Seems a bit wasteful to return the roots in a slice and map. Can you make this work with just the map?

beacon-chain/db/kv/blocks.go Outdated Show resolved Hide resolved
defer span.End()

// Perform all deletions in a single transaction for atomicity
return s.db.Update(func(tx *bolt.Tx) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you are not deleting everything you should. Looking at bucket names, there are also:

  • checkpointBucket (if this bucket stores what the name suggests, then if we remove an old checkpoint block, this bucket will still contain the checkpoint)
  • stateValidatorsBucket (I think this one is very important because validators are a big chunk of the state)
  • blockParentRootIndicesBucket
  • stateSlotIndicesBucket
  • finalizedBlockRootsIndexBucket
  • blockRootValidatorHashesBucket
  • originCheckpointBlockRootKey (I don't know the implications of removing this, it's best to ask @kasey about it. The bucket is used in a few places, but after the first pruning the origin checkpoint will "move". Shouldn't we update the value in the bucket accordingly?)

Comment on lines +271 to +274
// Delete block from cache
s.blockCache.Del(string(root))
// Delete state summary from cache
s.stateSummaryCache.delete([32]byte(root))
Copy link
Contributor

Choose a reason for hiding this comment

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

This might not be very important to fix, but if the transaction fails these deletions will not roll back. Maybe it would be better to store a slice of roots and then clear caches after the transaction completes? The downside of this is allocating the slice.

for {
select {
case <-p.ctx.Done():
return
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we debug log something?

case <-p.ctx.Done():
return
case <-p.done:
return
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we debug log something?

beacon-chain/db/pruner/pruner.go Outdated Show resolved Hide resolved
beacon-chain/db/pruner/pruner_test.go Outdated Show resolved Hide resolved
beacon-chain/db/pruner/pruner_test.go Outdated Show resolved Hide resolved
@rkapka
Copy link
Contributor

rkapka commented Dec 30, 2024

Additional comment:

How about removing data for each bucket (or at least each major one) in parallel instead of block,state,block,state...? Using a wait group (I think) to make sure we wait for everything before the transaction completes. Before doing that we should check how long it takes to prune in the unhappy case. If it's a 100ms, then no need to optimize, but if it's 10s then it's worth it. The question then becomes what actually is the unhappy case? How many epochs of non-finality can the pruner expect? I am also wondering what happens when the pruner takes more than 12s to complete, as this will kick the next round of pruning before the previous has even completed. But that's probably a very unhappy case lol.

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