reuse claim memory

This commit is contained in:
Brannon King 2021-08-09 10:02:03 -04:00
parent ccfa7af546
commit 531428d306
8 changed files with 74 additions and 24 deletions

View file

@ -163,6 +163,9 @@ func (b *BlockChain) GetClaimsForName(height int32, name string) (string, *node.
n, err := b.claimTrie.NodeAt(height, normalizedName) n, err := b.claimTrie.NodeAt(height, normalizedName)
if err != nil { if err != nil {
if n != nil {
n.Close()
}
return string(normalizedName), nil, err return string(normalizedName), nil, err
} }

View file

@ -119,6 +119,7 @@ func TestNormalizationFork(t *testing.T) {
r.NoError(err) r.NoError(err)
r.NotNil(n.BestClaim) r.NotNil(n.BestClaim)
r.Equal(int32(1), n.TakenOverAt) r.Equal(int32(1), n.TakenOverAt)
n.Close()
o8 := wire.OutPoint{Hash: hash, Index: 8} o8 := wire.OutPoint{Hash: hash, Index: 8}
err = ct.AddClaim([]byte("aÑEJO"), o8, change.NewClaimID(o8), 8) err = ct.AddClaim([]byte("aÑ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")) n, err = ct.nodeManager.NodeAt(ct.nodeManager.Height(), []byte("test"))
r.NoError(err) r.NoError(err)
r.Equal(int64(18), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()]) r.Equal(int64(18), n.BestClaim.Amount+n.SupportSums[n.BestClaim.ClaimID.Key()])
n.Close()
} }
func TestActivationsOnNormalizationFork(t *testing.T) { func TestActivationsOnNormalizationFork(t *testing.T) {
@ -227,6 +229,7 @@ func verifyBestIndex(t *testing.T, ct *ClaimTrie, name string, idx uint32, claim
if claims > 0 { if claims > 0 {
r.Equal(idx, n.BestClaim.OutPoint.Index) r.Equal(idx, n.BestClaim.OutPoint.Index)
} }
n.Close()
} }
func TestRebuild(t *testing.T) { func TestRebuild(t *testing.T) {

View file

@ -103,6 +103,7 @@ func NewNodeReplayCommand() *cobra.Command {
} }
showNode(n) showNode(n)
n.Close()
return nil return nil
}, },
} }

View file

@ -64,6 +64,7 @@ func (nc *nodeCache) Put(key string, element *Node) {
} else if len(nc.elements) >= nc.maxElements { } else if len(nc.elements) >= nc.maxElements {
existing = nc.data.Back() existing = nc.data.Back()
delete(nc.elements, existing.Value.(nodeCacheLeaf).key) delete(nc.elements, existing.Value.(nodeCacheLeaf).key)
existing.Value.(nodeCacheLeaf).node.Close()
existing.Value = nodeCacheLeaf{element, key} existing.Value = nodeCacheLeaf{element, key}
nc.data.MoveToFront(existing) nc.data.MoveToFront(existing)
nc.elements[key] = 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) n, err := nm.newNodeFromChanges(changes, height)
if err != nil { if err != nil {
if n != nil {
n.Close()
}
return nil, errors.Wrap(err, "in new node") 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) delay := nm.getDelayForName(n, chg)
err := n.ApplyChange(chg, delay) err := n.ApplyChange(chg, delay)
if err != nil { if err != nil {
n.Close()
return nil, errors.Wrap(err, "in apply change") return nil, errors.Wrap(err, "in apply change")
} }
} }
if count <= 0 { if count <= 0 {
n.Close()
return nil, nil return nil, nil
} }
lastChange := changes[count-1] lastChange := changes[count-1]
@ -425,12 +431,15 @@ 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 return true // children that are spent in the same block cannot count as active children
} }
n, _ := nm.newNodeFromChanges(changes, height) n, _ := nm.newNodeFromChanges(changes, height)
if n != nil && n.HasActiveBestClaim() { if n != nil {
defer n.Close()
if n.HasActiveBestClaim() {
c[changes[0].Name[len(name)]] = true c[changes[0].Name[len(name)]] = true
if len(c) >= required { if len(c) >= required {
return false return false
} }
} }
}
return true return true
}) })
return err == nil && len(c) >= required return err == nil && len(c) >= required

View file

@ -154,6 +154,7 @@ func TestNodeSort(t *testing.T) {
r.True(OutPointLess(*out1, *out3)) r.True(OutPointLess(*out1, *out3))
n := New() 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: *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.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{2}})
n.handleExpiredAndActivated(3) n.handleExpiredAndActivated(3)
@ -174,6 +175,7 @@ func TestClaimSort(t *testing.T) {
param.ActiveParams.ExtendedClaimExpirationTime = 1000 param.ActiveParams.ExtendedClaimExpirationTime = 1000
n := New() 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: *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: 3, Amount: 2, ClaimID: change.ClaimID{3}})
n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 4, Amount: 2, ClaimID: change.ClaimID{4}}) n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 4, Amount: 2, ClaimID: change.ClaimID{4}})

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"math" "math"
"sort" "sort"
"sync"
"github.com/btcsuite/btcd/claimtrie/change" "github.com/btcsuite/btcd/claimtrie/change"
"github.com/btcsuite/btcd/claimtrie/param" "github.com/btcsuite/btcd/claimtrie/param"
@ -26,6 +27,27 @@ func (n *Node) HasActiveBestClaim() bool {
return n.BestClaim != nil && n.BestClaim.Status == Activated 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 { func (n *Node) ApplyChange(chg change.Change, delay int32) error {
visibleAt := chg.VisibleHeight visibleAt := chg.VisibleHeight
@ -35,17 +57,19 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
switch chg.Type { switch chg.Type {
case change.AddClaim: case change.AddClaim:
c := &Claim{ c := claimPool.Get().(*Claim)
OutPoint: chg.OutPoint, // set all 8 fields on c as they aren't initialized to 0:
Amount: chg.Amount, c.Status = Accepted
ClaimID: chg.ClaimID, c.OutPoint = chg.OutPoint
c.Amount = chg.Amount
c.ClaimID = chg.ClaimID
// CreatedAt: chg.Height, // CreatedAt: chg.Height,
AcceptedAt: chg.Height, c.AcceptedAt = chg.Height
ActiveAt: chg.Height + delay, c.ActiveAt = chg.Height + delay
VisibleAt: visibleAt, c.VisibleAt = visibleAt
Sequence: int32(len(n.Claims)), c.Sequence = int32(len(n.Claims))
} // removed this after proving ResetHeight works:
// old := n.Claims.find(byOut(chg.OutPoint)) // TODO: remove this after proving ResetHeight works // old := n.Claims.find(byOut(chg.OutPoint))
// if old != nil { // if old != nil {
// return errors.Errorf("CONFLICT WITH EXISTING TXO! Name: %s, Height: %d", chg.Name, chg.Height) // 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 // 'two' at 481100, 36a719a156a1df178531f3c712b8b37f8e7cc3b36eea532df961229d936272a1:0
case change.UpdateClaim: case change.UpdateClaim:
// Find and remove the claim, which has just been spent.
c := n.Claims.find(byID(chg.ClaimID)) c := n.Claims.find(byID(chg.ClaimID))
if c != nil && c.Status == Deactivated { 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)) LogOnce(fmt.Sprintf("Updating claim but missing existing claim with ID %s", chg.ClaimID))
} }
case change.AddSupport: case change.AddSupport:
n.Supports = append(n.Supports, &Claim{ s := claimPool.Get().(*Claim)
OutPoint: chg.OutPoint, // set all 8 fields on s:
Amount: chg.Amount, s.Status = Accepted
ClaimID: chg.ClaimID, s.OutPoint = chg.OutPoint
AcceptedAt: chg.Height, s.Amount = chg.Amount
ActiveAt: chg.Height + delay, s.ClaimID = chg.ClaimID
VisibleAt: visibleAt, 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: case change.SpendSupport:
s := n.Supports.find(byOut(chg.OutPoint)) s := n.Supports.find(byOut(chg.OutPoint))

View file

@ -77,6 +77,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3
if err != nil || n == nil { if err != nil || n == nil {
return true return true
} }
defer n.Close()
for _, c := range n.Claims { for _, c := range n.Claims {
nm.Manager.AppendChange(change.Change{ nm.Manager.AppendChange(change.Change{
Type: change.AddClaim, Type: change.AddClaim,

View file

@ -105,6 +105,7 @@ func handleGetClaimsForName(s *rpcServer, cmd interface{}, _ <-chan struct{}) (i
Message: "Message: " + err.Error(), Message: "Message: " + err.Error(),
} }
} }
defer n.Close()
var results []btcjson.ClaimResult var results []btcjson.ClaimResult
for i := range n.Claims { for i := range n.Claims {
@ -138,6 +139,7 @@ func handleGetClaimsForNameByID(s *rpcServer, cmd interface{}, _ <-chan struct{}
Message: "Message: " + err.Error(), Message: "Message: " + err.Error(),
} }
} }
defer n.Close()
var results []btcjson.ClaimResult var results []btcjson.ClaimResult
for i := 0; i < len(n.Claims); i++ { for i := 0; i < len(n.Claims); i++ {
@ -176,6 +178,7 @@ func handleGetClaimsForNameByBid(s *rpcServer, cmd interface{}, _ <-chan struct{
Message: "Message: " + err.Error(), Message: "Message: " + err.Error(),
} }
} }
defer n.Close()
var results []btcjson.ClaimResult var results []btcjson.ClaimResult
for _, b := range c.Bids { // claims are already sorted in bid order 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(), Message: "Message: " + err.Error(),
} }
} }
defer n.Close()
sm := map[int32]bool{} sm := map[int32]bool{}
for _, seq := range c.Sequences { for _, seq := range c.Sequences {