diff options
author | Péter Szilágyi <peterke@gmail.com> | 2019-04-02 22:03:12 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-02 22:03:12 +0800 |
commit | e14f8a408c17fd6c57d769cd4635ad6cc8bde769 (patch) | |
tree | ba0d75fe1d1797be2322366e3d74cc54f77a6184 /core/blockchain_insert.go | |
parent | 88d7119ebb7bcb38e16f0feb571c98f2197d7cf3 (diff) | |
parent | ed34a5e08a475fdf1b3116b1f17879411bfe411d (diff) | |
download | go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.gz go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.bz2 go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.lz go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.xz go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.zst go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.zip |
Merge pull request #19328 from karalabe/preload
core: prefetch next block state concurrently
Diffstat (limited to 'core/blockchain_insert.go')
-rw-r--r-- | core/blockchain_insert.go | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index e2a385164..e4d758d4c 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -80,10 +80,13 @@ func (st *insertStats) report(chain []*types.Block, index int, dirty common.Stor // insertIterator is a helper to assist during chain import. type insertIterator struct { - chain types.Blocks - results <-chan error - index int - validator Validator + chain types.Blocks // Chain of blocks being iterated over + + results <-chan error // Verification result sink from the consensus engine + errors []error // Header verification errors for the blocks + + index int // Current offset of the iterator + validator Validator // Validator to run if verification succeeds } // newInsertIterator creates a new iterator based on the given blocks, which are @@ -92,6 +95,7 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid return &insertIterator{ chain: chain, results: results, + errors: make([]error, 0, len(chain)), index: -1, validator: validator, } @@ -100,17 +104,44 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid // next returns the next block in the iterator, along with any potential validation // error for that block. When the end is reached, it will return (nil, nil). func (it *insertIterator) next() (*types.Block, error) { + // If we reached the end of the chain, abort if it.index+1 >= len(it.chain) { it.index = len(it.chain) return nil, nil } + // Advance the iterator and wait for verification result if not yet done it.index++ - if err := <-it.results; err != nil { - return it.chain[it.index], err + if len(it.errors) <= it.index { + it.errors = append(it.errors, <-it.results) + } + if it.errors[it.index] != nil { + return it.chain[it.index], it.errors[it.index] } + // Block header valid, run body validation and return return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index]) } +// peek returns the next block in the iterator, along with any potential validation +// error for that block, but does **not** advance the iterator. +// +// Both header and body validation errors (nil too) is cached into the iterator +// to avoid duplicating work on the following next() call. +func (it *insertIterator) peek() (*types.Block, error) { + // If we reached the end of the chain, abort + if it.index+1 >= len(it.chain) { + return nil, nil + } + // Wait for verification result if not yet done + if len(it.errors) <= it.index+1 { + it.errors = append(it.errors, <-it.results) + } + if it.errors[it.index+1] != nil { + return it.chain[it.index+1], it.errors[it.index+1] + } + // Block header valid, ignore body validation since we don't have a parent anyway + return it.chain[it.index+1], nil +} + // previous returns the previous header that was being processed, or nil. func (it *insertIterator) previous() *types.Header { if it.index < 1 { |