From bf84e1f2fbfb20660dfeeebe73c6420334fd6ce4 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 23 Dec 2019 19:18:12 +0300 Subject: [PATCH] core: cache top block Turns out, our dApps use it a lot and we were going to the DB to get it which is a useless waste of time. Technically we could also remove blockHeight here, but not doing it at the moment as it's more involved. It eliminates this time waste from the pprof graph, but doesn't change 1.4M -> 1.5M 100K mainnet block import test case in any noticeable way. --- pkg/core/blockchain.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 18f589832..863da412d 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -55,6 +55,9 @@ type Blockchain struct { // Write access should only happen in storeBlock(). blockHeight uint32 + // Current top Block wrapped in an atomic.Value for safe access. + topBlock atomic.Value + // Current persisted block count. persistedHeight uint32 @@ -558,6 +561,7 @@ func (bc *Blockchain) storeBlock(block *Block) error { if err != nil { return err } + bc.topBlock.Store(block) atomic.StoreUint32(&bc.blockHeight, block.Index) updateBlockHeightMetric(block.Index) for _, tx := range block.Transactions { @@ -749,6 +753,13 @@ func (bc *Blockchain) GetStorageItems(hash util.Uint160) (map[string]*state.Stor // GetBlock returns a Block by the given hash. func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { + topBlock := bc.topBlock.Load() + if topBlock != nil { + if tb, ok := topBlock.(*Block); ok && tb.Hash().Equals(hash) { + return tb, nil + } + } + block, err := bc.dao.GetBlock(hash) if err != nil { return nil, err @@ -768,6 +779,12 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { // GetHeader returns data block header identified with the given hash value. func (bc *Blockchain) GetHeader(hash util.Uint256) (*Header, error) { + topBlock := bc.topBlock.Load() + if topBlock != nil { + if tb, ok := topBlock.(*Block); ok && tb.Hash().Equals(hash) { + return tb.Header(), nil + } + } block, err := bc.dao.GetBlock(hash) if err != nil { return nil, err