diff --git a/blockdag/reachability.go b/blockdag/reachability.go index 3d44a7e99..8f785c0d4 100644 --- a/blockdag/reachability.go +++ b/blockdag/reachability.go @@ -311,7 +311,7 @@ func (rtn *reachabilityTreeNode) countSubtrees(subTreeSizeMap map[*reachabilityT if len(current.children) == 0 { // We reached a leaf subTreeSizeMap[current] = 1 - } else if calculatedChildrenCount[current] <= uint64(len(current.children)) { + } else if _, ok := subTreeSizeMap[current]; !ok { // We haven't yet calculated the subtree size of // the current node. Add all its children to the // queue diff --git a/blockdag/reachability_test.go b/blockdag/reachability_test.go index 5a6a5fce9..c2d8c1e84 100644 --- a/blockdag/reachability_test.go +++ b/blockdag/reachability_test.go @@ -609,6 +609,46 @@ func TestReindexIntervalErrors(t *testing.T) { } } +func BenchmarkReindexInterval(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + root := newReachabilityTreeNode(&blockNode{}) + + const subTreeSize = 70000 + // We set the interval of the root to subTreeSize*2 because + // its first child gets half of the interval, so a reindex + // from the root should happen after adding subTreeSize + // nodes. + root.setInterval(newReachabilityInterval(0, subTreeSize*2)) + + currentTreeNode := root + for i := 0; i < subTreeSize; i++ { + childTreeNode := newReachabilityTreeNode(&blockNode{}) + _, err := currentTreeNode.addChild(childTreeNode) + if err != nil { + b.Fatalf("addChild: %s", err) + } + + currentTreeNode = childTreeNode + } + + remainingIntervalBefore := *root.remainingInterval + // After we added subTreeSize nodes, adding the next + // node should lead to a reindex from root. + fullReindexTriggeringNode := newReachabilityTreeNode(&blockNode{}) + b.StartTimer() + _, err := currentTreeNode.addChild(fullReindexTriggeringNode) + b.StopTimer() + if err != nil { + b.Fatalf("addChild: %s", err) + } + + if *root.remainingInterval == remainingIntervalBefore { + b.Fatal("Expected a reindex from root, but it didn't happen") + } + } +} + func TestFutureCoveringBlockSetString(t *testing.T) { treeNodeA := newReachabilityTreeNode(&blockNode{}) treeNodeA.setInterval(newReachabilityInterval(123, 456))