From 531428d3067861abd6076e950d120d0972cac257 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Mon, 9 Aug 2021 10:02:03 -0400 Subject: [PATCH] reuse claim memory --- blockchain/claimtrie.go | 3 ++ claimtrie/claimtrie_test.go | 3 ++ claimtrie/cmd/cmd/node.go | 1 + claimtrie/node/manager.go | 17 +++++-- claimtrie/node/manager_test.go | 2 + claimtrie/node/node.go | 67 +++++++++++++++++++-------- claimtrie/node/normalizing_manager.go | 1 + rpcclaimtrie.go | 4 ++ 8 files changed, 74 insertions(+), 24 deletions(-) diff --git a/blockchain/claimtrie.go b/blockchain/claimtrie.go index b0ce8443..5e7c0a02 100644 --- a/blockchain/claimtrie.go +++ b/blockchain/claimtrie.go @@ -163,6 +163,9 @@ func (b *BlockChain) GetClaimsForName(height int32, name string) (string, *node. n, err := b.claimTrie.NodeAt(height, normalizedName) if err != nil { + if n != nil { + n.Close() + } return string(normalizedName), nil, err } diff --git a/claimtrie/claimtrie_test.go b/claimtrie/claimtrie_test.go index ab77e287..5ce447b0 100644 --- a/claimtrie/claimtrie_test.go +++ b/claimtrie/claimtrie_test.go @@ -119,6 +119,7 @@ func TestNormalizationFork(t *testing.T) { r.NoError(err) r.NotNil(n.BestClaim) r.Equal(int32(1), n.TakenOverAt) + n.Close() o8 := wire.OutPoint{Hash: hash, Index: 8} err = ct.AddClaim([]byte("aN˃EJO"), o8, change.NewClaimID(o8), 8) @@ -137,6 +138,7 @@ func TestNormalizationFork(t *testing.T) { n, err = ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte("test")) r.NoError(err) r.Equal(int64(18), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()]) + n.Close() } func TestActivationsOnNormalizationFork(t *testing.T) { @@ -227,6 +229,7 @@ func verifyBestIndex(t *testing.T, ct *ClaimTrie, name string, idx uint32, claim if claims > 0 { r.Equal(idx, n.BestClaim.OutPoint.Index) } + n.Close() } func TestRebuild(t *testing.T) { diff --git a/claimtrie/cmd/cmd/node.go b/claimtrie/cmd/cmd/node.go index 49049916..d3891c27 100644 --- a/claimtrie/cmd/cmd/node.go +++ b/claimtrie/cmd/cmd/node.go @@ -103,6 +103,7 @@ func NewNodeReplayCommand() *cobra.Command { } showNode(n) + n.Close() return nil }, } diff --git a/claimtrie/node/manager.go b/claimtrie/node/manager.go index ebee73bb..48988c22 100644 --- a/claimtrie/node/manager.go +++ b/claimtrie/node/manager.go @@ -64,6 +64,7 @@ func (nc *nodeCache) Put(key string, element *Node) { } else if len(nc.elements) >= nc.maxElements { existing = nc.data.Back() delete(nc.elements, existing.Value.(nodeCacheLeaf).key) + existing.Value.(nodeCacheLeaf).node.Close() existing.Value = nodeCacheLeaf{element, key} nc.data.MoveToFront(existing) nc.elements[key] = existing @@ -107,6 +108,9 @@ func (nm *BaseManager) NodeAt(height int32, name []byte) (*Node, error) { n, err := nm.newNodeFromChanges(changes, height) if err != nil { + if n != nil { + n.Close() + } return nil, errors.Wrap(err, "in new node") } @@ -161,11 +165,13 @@ func (nm *BaseManager) newNodeFromChanges(changes []change.Change, height int32) delay := nm.getDelayForName(n, chg) err := n.ApplyChange(chg, delay) if err != nil { + n.Close() return nil, errors.Wrap(err, "in apply change") } } if count <= 0 { + n.Close() return nil, nil } lastChange := changes[count-1] @@ -425,10 +431,13 @@ func (nm *BaseManager) hasChildren(name []byte, height int32, spentChildren map[ return true // children that are spent in the same block cannot count as active children } n, _ := nm.newNodeFromChanges(changes, height) - if n != nil && n.HasActiveBestClaim() { - c[changes[0].Name[len(name)]] = true - if len(c) >= required { - return false + if n != nil { + defer n.Close() + if n.HasActiveBestClaim() { + c[changes[0].Name[len(name)]] = true + if len(c) >= required { + return false + } } } return true diff --git a/claimtrie/node/manager_test.go b/claimtrie/node/manager_test.go index 6dd61a97..64b185cd 100644 --- a/claimtrie/node/manager_test.go +++ b/claimtrie/node/manager_test.go @@ -154,6 +154,7 @@ func TestNodeSort(t *testing.T) { r.True(OutPointLess(*out1, *out3)) n := New() + defer n.Close() n.Claims = append(n.Claims, &Claim{OutPoint: *out1, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{1}}) n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{2}}) n.handleExpiredAndActivated(3) @@ -174,6 +175,7 @@ func TestClaimSort(t *testing.T) { param.ActiveParams.ExtendedClaimExpirationTime = 1000 n := New() + defer n.Close() n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{2}}) n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 3, Amount: 2, ClaimID: change.ClaimID{3}}) n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 4, Amount: 2, ClaimID: change.ClaimID{4}}) diff --git a/claimtrie/node/node.go b/claimtrie/node/node.go index f48dee3c..72bbe29e 100644 --- a/claimtrie/node/node.go +++ b/claimtrie/node/node.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "sort" + "sync" "github.com/btcsuite/btcd/claimtrie/change" "github.com/btcsuite/btcd/claimtrie/param" @@ -26,6 +27,27 @@ func (n *Node) HasActiveBestClaim() bool { return n.BestClaim != nil && n.BestClaim.Status == Activated } +var claimPool = sync.Pool{ + New: func() interface{} { + return &Claim{} + }, +} + +func (n *Node) Close() { + n.BestClaim = nil + n.SupportSums = nil + + for i := range n.Claims { + claimPool.Put(n.Claims[i]) + } + n.Claims = nil + + for i := range n.Supports { + claimPool.Put(n.Supports[i]) + } + n.Supports = nil +} + func (n *Node) ApplyChange(chg change.Change, delay int32) error { visibleAt := chg.VisibleHeight @@ -35,17 +57,19 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { switch chg.Type { case change.AddClaim: - c := &Claim{ - OutPoint: chg.OutPoint, - Amount: chg.Amount, - ClaimID: chg.ClaimID, - // CreatedAt: chg.Height, - AcceptedAt: chg.Height, - ActiveAt: chg.Height + delay, - VisibleAt: visibleAt, - Sequence: int32(len(n.Claims)), - } - // old := n.Claims.find(byOut(chg.OutPoint)) // TODO: remove this after proving ResetHeight works + c := claimPool.Get().(*Claim) + // set all 8 fields on c as they aren't initialized to 0: + c.Status = Accepted + c.OutPoint = chg.OutPoint + c.Amount = chg.Amount + c.ClaimID = chg.ClaimID + // CreatedAt: chg.Height, + c.AcceptedAt = chg.Height + c.ActiveAt = chg.Height + delay + c.VisibleAt = visibleAt + c.Sequence = int32(len(n.Claims)) + // removed this after proving ResetHeight works: + // old := n.Claims.find(byOut(chg.OutPoint)) // if old != nil { // return errors.Errorf("CONFLICT WITH EXISTING TXO! Name: %s, Height: %d", chg.Name, chg.Height) // } @@ -63,7 +87,6 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { // 'two' at 481100, 36a719a156a1df178531f3c712b8b37f8e7cc3b36eea532df961229d936272a1:0 case change.UpdateClaim: - // Find and remove the claim, which has just been spent. c := n.Claims.find(byID(chg.ClaimID)) if c != nil && c.Status == Deactivated { @@ -82,14 +105,18 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { LogOnce(fmt.Sprintf("Updating claim but missing existing claim with ID %s", chg.ClaimID)) } case change.AddSupport: - n.Supports = append(n.Supports, &Claim{ - OutPoint: chg.OutPoint, - Amount: chg.Amount, - ClaimID: chg.ClaimID, - AcceptedAt: chg.Height, - ActiveAt: chg.Height + delay, - VisibleAt: visibleAt, - }) + s := claimPool.Get().(*Claim) + // set all 8 fields on s: + s.Status = Accepted + s.OutPoint = chg.OutPoint + s.Amount = chg.Amount + s.ClaimID = chg.ClaimID + s.AcceptedAt = chg.Height + s.ActiveAt = chg.Height + delay + s.VisibleAt = visibleAt + s.Sequence = int32(len(n.Supports)) + + n.Supports = append(n.Supports, s) case change.SpendSupport: s := n.Supports.find(byOut(chg.OutPoint)) diff --git a/claimtrie/node/normalizing_manager.go b/claimtrie/node/normalizing_manager.go index 2bce7d86..d5286e6e 100644 --- a/claimtrie/node/normalizing_manager.go +++ b/claimtrie/node/normalizing_manager.go @@ -77,6 +77,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3 if err != nil || n == nil { return true } + defer n.Close() for _, c := range n.Claims { nm.Manager.AppendChange(change.Change{ Type: change.AddClaim, diff --git a/rpcclaimtrie.go b/rpcclaimtrie.go index 6a90152e..929aa4f0 100644 --- a/rpcclaimtrie.go +++ b/rpcclaimtrie.go @@ -105,6 +105,7 @@ func handleGetClaimsForName(s *rpcServer, cmd interface{}, _ <-chan struct{}) (i Message: "Message: " + err.Error(), } } + defer n.Close() var results []btcjson.ClaimResult for i := range n.Claims { @@ -138,6 +139,7 @@ func handleGetClaimsForNameByID(s *rpcServer, cmd interface{}, _ <-chan struct{} Message: "Message: " + err.Error(), } } + defer n.Close() var results []btcjson.ClaimResult for i := 0; i < len(n.Claims); i++ { @@ -176,6 +178,7 @@ func handleGetClaimsForNameByBid(s *rpcServer, cmd interface{}, _ <-chan struct{ Message: "Message: " + err.Error(), } } + defer n.Close() var results []btcjson.ClaimResult for _, b := range c.Bids { // claims are already sorted in bid order @@ -211,6 +214,7 @@ func handleGetClaimsForNameBySeq(s *rpcServer, cmd interface{}, _ <-chan struct{ Message: "Message: " + err.Error(), } } + defer n.Close() sm := map[int32]bool{} for _, seq := range c.Sequences {