From b66bc33cf92945d328c4ae47da8568bbb064d928 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 22 Sep 2021 10:50:26 +0300 Subject: [PATCH 1/2] native: short-circuit successive GAS distributions GAS can only be distributed once in a block for particular address, so it makes little sense trying to calculate it again and again. This fixes neo-bench for NEO voter, because without it we get ~2500 TPS for single-address test and with it it jumps 13-fold to normal values like ~33500. --- pkg/core/native/native_neo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 133870c54..9df6e468b 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -434,7 +434,7 @@ func (n *NEO) balanceFromBytes(si *state.StorageItem) (*big.Int, error) { } func (n *NEO) distributeGas(ic *interop.Context, h util.Uint160, acc *state.NEOBalance) error { - if ic.Block == nil || ic.Block.Index == 0 { + if ic.Block == nil || ic.Block.Index == 0 || ic.Block.Index == acc.BalanceHeight { return nil } gen, err := n.calculateBonus(ic.DAO, acc.VoteTo, &acc.Balance, acc.BalanceHeight, ic.Block.Index) From c009356b73da92edaa340046d301de1b9129a387 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 22 Sep 2021 13:38:53 +0300 Subject: [PATCH 2/2] core: simplify component flushing in storeBlock Instead of flushing everything to `cache` and then to `bc.dao`, wrap `bc.dao` directly for block/tx data and AERs and then flush to it. Block/transactions are usually processed more quickly than other components, so they easily end up in `cache` where they directly affect Seek performance for any executing transaction. Simple as it is this change improves voter NEO transfer benchmark with 1000 accounts by more than 25%, from ~18500 TPS to ~23500 TPS. It doesn't affect much other cases. --- pkg/core/blockchain.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 719af0115..896751e38 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -904,6 +904,8 @@ func (bc *Blockchain) GetStateSyncModule() blockchainer.StateSync { func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error { var ( cache = bc.dao.GetWrapped() + blockCache = bc.dao.GetWrapped() + aerCache = bc.dao.GetWrapped() appExecResults = make([]*state.AppExecResult, 0, 2+len(block.Transactions)) aerchan = make(chan *state.AppExecResult, len(block.Transactions)/8) // Tested 8 and 4 with no practical difference, but feel free to test more and tune. aerdone = make(chan error) @@ -911,7 +913,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error ) go func() { var ( - kvcache = cache.GetWrapped() + kvcache = blockCache writeBuf = io.NewBufBinWriter() ) if err := kvcache.StoreAsBlock(block, writeBuf); err != nil { @@ -960,15 +962,11 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error writeBuf.Reset() } } - _, err := kvcache.Persist() - if err != nil { - blockdone <- err - } close(blockdone) }() go func() { var ( - kvcache = cache.GetWrapped() + kvcache = aerCache writeBuf = io.NewBufBinWriter() err error appendBlock bool @@ -1010,11 +1008,6 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error return } } - - _, err = kvcache.Persist() - if err != nil { - aerdone <- err - } close(aerdone) }() aer, err := bc.runPersist(bc.contracts.GetPersistScript(), block, cache, trigger.OnPersist) @@ -1129,6 +1122,16 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error } bc.lock.Lock() + _, err = blockCache.Persist() + if err != nil { + bc.lock.Unlock() + return err + } + _, err = aerCache.Persist() + if err != nil { + bc.lock.Unlock() + return err + } _, err = cache.Persist() if err != nil { bc.lock.Unlock()