Speedup iteration of blocks in sidechain using iterationCache

This commit is contained in:
DataHoarder 2023-07-05 11:37:27 +02:00
parent 5c24136e45
commit b57226c7ed
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 66 additions and 45 deletions

View file

@ -495,15 +495,23 @@ func (c *SideChain) verifyLoop(blockToVerify *PoolBlock) (err error) {
// This block is now verified
// Fill cache here
block.iterationCache = &IterationCache{
Parent: c.getParent(block),
Uncles: nil,
}
if len(block.Side.Uncles) > 0 {
block.iterationCache.Uncles = make([]*PoolBlock, 0, len(block.Side.Uncles))
for _, uncleId := range block.Side.Uncles {
block.iterationCache.Uncles = append(block.iterationCache.Uncles, c.getPoolBlockByTemplateId(uncleId))
if parent := c.getParent(block); parent != nil {
block.iterationCache = &IterationCache{
Parent: parent,
Uncles: nil,
}
if len(block.Side.Uncles) > 0 {
block.iterationCache.Uncles = make([]*PoolBlock, 0, len(block.Side.Uncles))
for _, uncleId := range block.Side.Uncles {
if uncle := c.getPoolBlockByTemplateId(uncleId); uncle == nil {
block.iterationCache = nil
break
} else {
block.iterationCache.Uncles = append(block.iterationCache.Uncles, uncle)
}
}
}
}
@ -766,7 +774,7 @@ func (c *SideChain) updateDepths(block *PoolBlock) {
for i := uint64(1); i <= UncleBlockDepth; i++ {
blocksAtHeight, _ := c.blocksByHeight.Get(block.Side.Height + i)
for _, child := range blocksAtHeight {
if child.Side.Parent.Equals(block.SideTemplateId(c.Consensus())) {
if child.Side.Parent == block.SideTemplateId(c.Consensus()) {
if i != 1 {
log.Printf("[SideChain] Block %s side height %d is inconsistent with parent's side_height %d", block.SideTemplateId(c.Consensus()), block.Side.Height, child.Side.Height)
return
@ -794,7 +802,7 @@ func (c *SideChain) updateDepths(block *PoolBlock) {
_ = c.verifyLoop(block)
}
if parent := c.getParent(block); parent != nil {
if parent := block.iteratorGetParent(c.getPoolBlockByTemplateId); parent != nil {
if parent.Side.Height+1 != block.Side.Height {
log.Printf("[SideChain] Block %s side height %d is inconsistent with parent's side_height %d", block.SideTemplateId(c.Consensus()), block.Side.Height, parent.Side.Height)
return
@ -806,19 +814,23 @@ func (c *SideChain) updateDepths(block *PoolBlock) {
}
}
for _, uncleId := range block.Side.Uncles {
if uncle := c.getPoolBlockByTemplateId(uncleId); uncle != nil {
if uncle.Side.Height >= block.Side.Height || (uncle.Side.Height+UncleBlockDepth < block.Side.Height) {
log.Printf("[SideChain] Block %s side height %d is inconsistent with uncle's side_height %d", block.SideTemplateId(c.Consensus()), block.Side.Height, uncle.Side.Height)
return
}
var returnFromUncles bool
d := block.Side.Height - uncle.Side.Height
if uncle.Depth.Load() < blockDepth+d {
uncle.Depth.Store(blockDepth + d)
blocksToUpdate = append(blocksToUpdate, uncle)
}
_ = block.iteratorUncles(c.getPoolBlockByTemplateId, func(uncle *PoolBlock) {
if uncle.Side.Height >= block.Side.Height || (uncle.Side.Height+UncleBlockDepth < block.Side.Height) {
log.Printf("[SideChain] Block %s side height %d is inconsistent with uncle's side_height %d", block.SideTemplateId(c.Consensus()), block.Side.Height, uncle.Side.Height)
returnFromUncles = true
return
}
d := block.Side.Height - uncle.Side.Height
if uncle.Depth.Load() < blockDepth+d {
uncle.Depth.Store(blockDepth + d)
blocksToUpdate = append(blocksToUpdate, uncle)
}
})
if returnFromUncles {
return
}
}
}
@ -967,14 +979,14 @@ func (c *SideChain) GetMissingBlocks() []types.Hash {
return false
}
if !b.Side.Parent.Equals(types.ZeroHash) && c.getPoolBlockByTemplateId(b.Side.Parent) == nil {
if b.Side.Parent != types.ZeroHash && c.getPoolBlockByTemplateId(b.Side.Parent) == nil {
missingBlocks = append(missingBlocks, b.Side.Parent)
}
missingUncles := 0
for _, uncleId := range b.Side.Uncles {
if !uncleId.Equals(types.ZeroHash) && c.getPoolBlockByTemplateId(uncleId) == nil {
if uncleId != types.ZeroHash && c.getPoolBlockByTemplateId(uncleId) == nil {
missingBlocks = append(missingBlocks, uncleId)
missingUncles++

View file

@ -290,3 +290,21 @@ func BenchmarkSideChainDefault_GetShares(b *testing.B) {
}
}
}
func BenchmarkSideChainDefault_BlocksInPPLNSWindow(b *testing.B) {
b.ReportAllocs()
tip := benchLoadedSideChain.GetChainTip()
b.ResetTimer()
var err error
for i := 0; i < b.N; i++ {
_, err = BlocksInPPLNSWindow(tip, benchLoadedSideChain.Consensus(), benchLoadedSideChain.server.GetDifficultyByHeight, benchLoadedSideChain.getPoolBlockByTemplateId, func(b *PoolBlock, weight types.Difficulty) {
})
if err != nil {
b.Error(err)
return
}
}
}

View file

@ -503,23 +503,23 @@ func IsLongerChain(block, candidate *PoolBlock, consensus *Consensus, getByTempl
blockAncestor := block
for blockAncestor != nil && blockAncestor.Side.Height > candidate.Side.Height {
blockAncestor = getByTemplateId(blockAncestor.Side.Parent)
blockAncestor = blockAncestor.iteratorGetParent(getByTemplateId)
//TODO: err on blockAncestor nil
}
if blockAncestor != nil {
candidateAncestor := candidate
for candidateAncestor != nil && candidateAncestor.Side.Height > blockAncestor.Side.Height {
candidateAncestor = getByTemplateId(candidateAncestor.Side.Parent)
candidateAncestor = candidateAncestor.iteratorGetParent(getByTemplateId)
//TODO: err on candidateAncestor nil
}
for blockAncestor != nil && candidateAncestor != nil {
if blockAncestor.Side.Parent.Equals(candidateAncestor.Side.Parent) {
if blockAncestor.Side.Parent == candidateAncestor.Side.Parent {
return block.Side.CumulativeDifficulty.Cmp(candidate.Side.CumulativeDifficulty) < 0, false
}
blockAncestor = getByTemplateId(blockAncestor.Side.Parent)
candidateAncestor = getByTemplateId(candidateAncestor.Side.Parent)
blockAncestor = blockAncestor.iteratorGetParent(getByTemplateId)
candidateAncestor = candidateAncestor.iteratorGetParent(getByTemplateId)
}
}
@ -538,15 +538,13 @@ func IsLongerChain(block, candidate *PoolBlock, consensus *Consensus, getByTempl
for i := uint64(0); i < consensus.ChainWindowSize && (oldChain != nil || newChain != nil); i++ {
if oldChain != nil {
blockTotalDiff = blockTotalDiff.Add(oldChain.Side.Difficulty)
for _, uncle := range oldChain.Side.Uncles {
if u := getByTemplateId(uncle); u != nil {
blockTotalDiff = blockTotalDiff.Add(u.Side.Difficulty)
}
}
_ = oldChain.iteratorUncles(getByTemplateId, func(uncle *PoolBlock) {
blockTotalDiff = blockTotalDiff.Add(uncle.Side.Difficulty)
})
if !slices.Contains(currentChainMoneroBlocks, oldChain.Main.PreviousId) && getChainMainByHash(oldChain.Main.PreviousId) != nil {
currentChainMoneroBlocks = append(currentChainMoneroBlocks, oldChain.Main.PreviousId)
}
oldChain = getByTemplateId(oldChain.Side.Parent)
oldChain = oldChain.iteratorGetParent(getByTemplateId)
}
if newChain != nil {
@ -556,11 +554,9 @@ func IsLongerChain(block, candidate *PoolBlock, consensus *Consensus, getByTempl
candidateMainchainMinHeight = newChain.Main.Coinbase.GenHeight
}
candidateTotalDiff = candidateTotalDiff.Add(newChain.Side.Difficulty)
for _, uncle := range newChain.Side.Uncles {
if u := getByTemplateId(uncle); u != nil {
candidateTotalDiff = candidateTotalDiff.Add(u.Side.Difficulty)
}
}
_ = newChain.iteratorUncles(getByTemplateId, func(uncle *PoolBlock) {
candidateTotalDiff = candidateTotalDiff.Add(uncle.Side.Difficulty)
})
if !slices.Contains(candidateChainMoneroBlocks, newChain.Main.PreviousId) {
if data := getChainMainByHash(newChain.Main.PreviousId); data != nil {
candidateChainMoneroBlocks = append(candidateChainMoneroBlocks, newChain.Main.PreviousId)
@ -568,7 +564,7 @@ func IsLongerChain(block, candidate *PoolBlock, consensus *Consensus, getByTempl
}
}
newChain = getByTemplateId(newChain.Side.Parent)
newChain = newChain.iteratorGetParent(getByTemplateId)
}
}

View file

@ -1,7 +1,6 @@
package types
import (
"bytes"
"database/sql/driver"
"encoding/hex"
"errors"
@ -92,10 +91,6 @@ func (h Hash) Compare(other Hash) int {
return 0
}
func (h Hash) Equals(o Hash) bool {
return bytes.Compare(h[:], o[:]) == 0
}
func (h Hash) String() string {
return hex.EncodeToString(h[:])
}