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

Batch save blocks for initial sync. 80% faster BPS #5215

Merged
merged 28 commits into from Mar 30, 2020
Merged

Conversation

terencechain
Copy link
Member

@terencechain terencechain commented Mar 26, 2020

This PR saves blocks in batch during initial sync. It holds the blocks in cache and batch saves the cached blocks into DB when there's a new finalized check point or the blocks count exceeds 64 (whichever comes first)

This is gated behind feature flag --init-sync-batch-save-blocks, I'm seeing on average 80-100% faster blocks per second versus current initial syncing.

This works and tested with the following flags:

--enable-ssz-cache 
--enable-state-field-trie 
--enable-byte-mempool
--enable-initial-sync-queue

I dont think it's compatible with new state mgmt flag yet

@codecov
Copy link

codecov bot commented Mar 26, 2020

Codecov Report

❗ No coverage uploaded for pull request base (master@0982ff1). Click here to learn what that means.
The diff coverage is 16.48%.

@@            Coverage Diff            @@
##             master    #5215   +/-   ##
=========================================
  Coverage          ?   39.22%           
=========================================
  Files             ?      231           
  Lines             ?    19102           
  Branches          ?        0           
=========================================
  Hits              ?     7492           
  Misses            ?    10274           
  Partials          ?     1336

@terencechain terencechain marked this pull request as ready for review March 28, 2020 17:34
@terencechain terencechain self-assigned this Mar 28, 2020
@terencechain terencechain changed the title Batch save blocks for initial sync Batch save blocks for initial sync, 80% speed improvement Mar 28, 2020
@terencechain terencechain changed the title Batch save blocks for initial sync, 80% speed improvement Batch save blocks for initial sync. 80% faster BPS Mar 28, 2020
@terencechain terencechain added the Ready For Review A pull request ready for code review label Mar 28, 2020
var endBlock *ethpb.SignedBeaconBlock
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(endRoot) {
endBlock = s.getInitSyncBlock(endRoot)
if featureconfig.Get().InitSyncBatchSaveBlocks {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this condition here? Wouldn't it already be true?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, thanks!

for _, block := range blocks {
if err := k.setBlockSlotBitField(ctx, tx, block.Block.Slot); err != nil {
return err
}

blockRoot, err := ssz.HashTreeRoot(block.Block)
blockRoot, err := stateutil.BlockRoot(block.Block)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

@@ -193,7 +203,7 @@ func (s *Service) roundRobinSync(genesis time.Time) error {
1, // step
blockBatchSize, // count
peers, // peers
0, // remainder
0, // reminder
Copy link
Contributor

Choose a reason for hiding this comment

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

Reminder? What does that mean in this context?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry it should have been remainder

log.Debugf("Beacon node doesn't have a block in db with root %#x", blk.Block.ParentRoot)
parentRoot := bytesutil.ToBytes32(blk.Block.ParentRoot)
if !s.db.HasBlock(ctx, parentRoot) && !s.chain.HasInitSyncBlock(parentRoot) {
log.Debugf("Beacon node doesn't have a block in db or cache with root %#x", parentRoot)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be changed to WithField() for better log tracking?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, not feature flag needed here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to WithField(), feature flag not needed in this csae

var endBlock *ethpb.SignedBeaconBlock
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(endRoot) {
endBlock = s.getInitSyncBlock(endRoot)
if featureconfig.Get().InitSyncBatchSaveBlocks {
Copy link
Member

Choose a reason for hiding this comment

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

why check again ? this will always be true

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed!

// This saves a beacon block to the initial sync blocks cache.
func (s *Service) saveInitSyncBlock(r [32]byte, b *ethpb.SignedBeaconBlock) {
s.initSyncBlocksLock.Lock()
defer s.initSyncBlocksLock.Unlock()
Copy link
Member

Choose a reason for hiding this comment

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

do we need a lock for this ? initial sync is single-threaded , so there isnt a risk of concurrent writes

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried without the lock, the performance is neglectable. Just figure be safe than sorry later if initial sync moves to multi threaded

@@ -247,6 +252,14 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
}
}

// Rate limit how many blocks (2 epochs worth of blocks) a node keeps in the memory.
if len(s.getInitSyncBlocks()) > 2*int(params.BeaconConfig().SlotsPerEpoch) {
Copy link
Member

Choose a reason for hiding this comment

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

can we make this value a configurable constant at the start of the file

Copy link
Member Author

Choose a reason for hiding this comment

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

yep, done!

@prylabs-bulldozer prylabs-bulldozer bot merged commit c5f186d into master Mar 30, 2020
@delete-merged-branch delete-merged-branch bot deleted the batch-save branch March 30, 2020 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ready For Review A pull request ready for code review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants