refactored EffectiveAmount for performance
This commit is contained in:
parent
f829fb6206
commit
a0469820a2
6 changed files with 103 additions and 43 deletions
|
@ -23,6 +23,8 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"runtime"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// ClaimTrie implements a Merkle Trie supporting linear history of commits.
|
||||
|
@ -110,18 +112,6 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
|||
return nil, fmt.Errorf("load blocks: %w", err)
|
||||
}
|
||||
|
||||
if previousHeight > 0 {
|
||||
hash, err := blockRepo.Get(previousHeight)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get hash: %w", err)
|
||||
}
|
||||
_, err = nodeManager.IncrementHeightTo(previousHeight)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("node manager init: %w", err)
|
||||
}
|
||||
trie.SetRoot(hash, nil) // keep this after IncrementHeightTo
|
||||
}
|
||||
|
||||
ct := &ClaimTrie{
|
||||
blockRepo: blockRepo,
|
||||
temporalRepo: temporalRepo,
|
||||
|
@ -149,6 +139,25 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
|||
}
|
||||
ct.cleanups = cleanups
|
||||
|
||||
if previousHeight > 0 {
|
||||
hash, err := blockRepo.Get(previousHeight)
|
||||
if err != nil {
|
||||
ct.Close() // TODO: the cleanups aren't run when we exit with an err above here (but should be)
|
||||
return nil, fmt.Errorf("get hash: %w", err)
|
||||
}
|
||||
_, err = nodeManager.IncrementHeightTo(previousHeight)
|
||||
if err != nil {
|
||||
ct.Close()
|
||||
return nil, fmt.Errorf("node manager init: %w", err)
|
||||
}
|
||||
trie.SetRoot(hash, nil) // keep this after IncrementHeightTo
|
||||
|
||||
if !ct.MerkleHash().IsEqual(hash) {
|
||||
ct.Close()
|
||||
return nil, fmt.Errorf("unable to restore the claim hash to %s at height %d", hash.String(), previousHeight)
|
||||
}
|
||||
}
|
||||
|
||||
return ct, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ func showClaim(c *node.Claim, n *node.Node) {
|
|||
mark = "*"
|
||||
}
|
||||
|
||||
fmt.Printf("%s C ID: %s, TXO: %s\n %5d/%-5d, Status: %9s, Amount: %15d, Effective Amount: %15d\n",
|
||||
mark, c.ClaimID, c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount, c.EffectiveAmount(n.Supports))
|
||||
fmt.Printf("%s C ID: %s, TXO: %s\n %5d/%-5d, Status: %9s, Amount: %15d, Support Amount: %15d\n",
|
||||
mark, c.ClaimID, c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount, n.SupportSums[c.ClaimID])
|
||||
}
|
||||
|
||||
func showSupport(c *node.Claim) {
|
||||
|
|
|
@ -101,23 +101,6 @@ func (c *Claim) setStatus(status Status) *Claim {
|
|||
return c
|
||||
}
|
||||
|
||||
func (c *Claim) EffectiveAmount(supports ClaimList) int64 {
|
||||
|
||||
if c.Status != Activated {
|
||||
return 0
|
||||
}
|
||||
|
||||
amt := c.Amount
|
||||
|
||||
for _, s := range supports {
|
||||
if s.Status == Activated && s.ClaimID == c.ClaimID { // TODO: this comparison is hit a lot; byte comparison instead of hex would be faster
|
||||
amt += s.Amount
|
||||
}
|
||||
}
|
||||
|
||||
return amt
|
||||
}
|
||||
|
||||
func (c *Claim) ExpireAt() int32 {
|
||||
|
||||
if c.AcceptedAt+param.OriginalClaimExpirationTime > param.ExtendedClaimExpirationForkHeight {
|
||||
|
|
|
@ -16,6 +16,7 @@ var (
|
|||
out1 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:1")
|
||||
out2 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:2")
|
||||
out3 = NewOutPointFromString("0100000000000000000000000000000000000000000000000000000000000000:1")
|
||||
out4 = NewOutPointFromString("0100000000000000000000000000000000000000000000000000000000000000:2")
|
||||
name1 = []byte("name1")
|
||||
name2 = []byte("name2")
|
||||
)
|
||||
|
@ -51,6 +52,7 @@ func TestSimpleAddClaim(t *testing.T) {
|
|||
|
||||
m, err := NewBaseManager(repo)
|
||||
r.NoError(err)
|
||||
defer m.Close()
|
||||
|
||||
_, err = m.IncrementHeightTo(10)
|
||||
r.NoError(err)
|
||||
|
@ -90,6 +92,58 @@ func TestSimpleAddClaim(t *testing.T) {
|
|||
r.Nil(n2)
|
||||
}
|
||||
|
||||
func TestSupportAmounts(t *testing.T) {
|
||||
|
||||
r := require.New(t)
|
||||
|
||||
param.SetNetwork(wire.TestNet, "")
|
||||
repo, err := noderepo.NewPebble(t.TempDir())
|
||||
r.NoError(err)
|
||||
|
||||
m, err := NewBaseManager(repo)
|
||||
r.NoError(err)
|
||||
defer m.Close()
|
||||
|
||||
_, err = m.IncrementHeightTo(10)
|
||||
r.NoError(err)
|
||||
|
||||
chg := change.New(change.AddClaim).SetName(name1).SetOutPoint(out1.String()).SetHeight(11).SetAmount(3)
|
||||
chg.ClaimID = NewClaimID(*out1).String()
|
||||
err = m.AppendChange(chg)
|
||||
r.NoError(err)
|
||||
|
||||
chg = change.New(change.AddClaim).SetName(name1).SetOutPoint(out2.String()).SetHeight(11).SetAmount(4)
|
||||
chg.ClaimID = NewClaimID(*out2).String()
|
||||
err = m.AppendChange(chg)
|
||||
r.NoError(err)
|
||||
|
||||
_, err = m.IncrementHeightTo(11)
|
||||
r.NoError(err)
|
||||
|
||||
chg = change.New(change.AddSupport).SetName(name1).SetOutPoint(out3.String()).SetHeight(12).SetAmount(2)
|
||||
chg.ClaimID = NewClaimID(*out1).String()
|
||||
err = m.AppendChange(chg)
|
||||
r.NoError(err)
|
||||
|
||||
chg = change.New(change.AddSupport).SetName(name1).SetOutPoint(out4.String()).SetHeight(12).SetAmount(2)
|
||||
chg.ClaimID = NewClaimID(*out2).String()
|
||||
err = m.AppendChange(chg)
|
||||
r.NoError(err)
|
||||
|
||||
chg = change.New(change.SpendSupport).SetName(name1).SetOutPoint(out4.String()).SetHeight(12).SetAmount(2)
|
||||
chg.ClaimID = NewClaimID(*out2).String()
|
||||
err = m.AppendChange(chg)
|
||||
r.NoError(err)
|
||||
|
||||
_, err = m.IncrementHeightTo(20)
|
||||
r.NoError(err)
|
||||
|
||||
n1, err := m.Node(name1)
|
||||
r.NoError(err)
|
||||
r.Equal(2, len(n1.Claims))
|
||||
r.Equal(int64(5), n1.BestClaim.Amount+n1.SupportSums[n1.BestClaim.ClaimID])
|
||||
}
|
||||
|
||||
func TestNodeSort(t *testing.T) {
|
||||
|
||||
r := require.New(t)
|
||||
|
|
|
@ -17,11 +17,12 @@ type Node struct {
|
|||
TakenOverAt int32 // The height at when the current BestClaim took over.
|
||||
Claims ClaimList // List of all Claims.
|
||||
Supports ClaimList // List of all Supports, including orphaned ones.
|
||||
SupportSums map[string]int64
|
||||
}
|
||||
|
||||
// New returns a new node.
|
||||
func New() *Node {
|
||||
return &Node{}
|
||||
return &Node{SupportSums: map[string]int64{}}
|
||||
}
|
||||
|
||||
func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
||||
|
@ -94,6 +95,12 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
|||
case change.SpendSupport:
|
||||
s := n.Supports.find(byOut(*out))
|
||||
if s != nil {
|
||||
if s.Status == Activated {
|
||||
n.SupportSums[s.ClaimID] -= s.Amount
|
||||
}
|
||||
// TODO: we could do without this Deactivated flag if we set expiration instead
|
||||
// That would eliminate the above Sum update.
|
||||
// We would also need to track the update situation, though, but that could be done locally.
|
||||
s.setStatus(Deactivated)
|
||||
} else {
|
||||
fmt.Printf("Spending support but missing existing support with TXO %s\n "+
|
||||
|
@ -151,12 +158,15 @@ func (n *Node) updateTakeoverHeight(height int32, name []byte, refindBest bool)
|
|||
func (n *Node) handleExpiredAndActivated(height int32) int {
|
||||
|
||||
changes := 0
|
||||
update := func(items ClaimList) ClaimList {
|
||||
update := func(items ClaimList, sums map[string]int64) ClaimList {
|
||||
for i := 0; i < len(items); i++ {
|
||||
c := items[i]
|
||||
if c.Status == Accepted && c.ActiveAt <= height && c.VisibleAt <= height {
|
||||
c.setStatus(Activated)
|
||||
changes++
|
||||
if sums != nil {
|
||||
sums[c.ClaimID] += c.Amount
|
||||
}
|
||||
}
|
||||
if c.ExpireAt() <= height || c.Status == Deactivated {
|
||||
if i < len(items)-1 {
|
||||
|
@ -165,12 +175,15 @@ func (n *Node) handleExpiredAndActivated(height int32) int {
|
|||
}
|
||||
items = items[:len(items)-1]
|
||||
changes++
|
||||
if sums != nil && c.Status != Deactivated {
|
||||
sums[c.ClaimID] -= c.Amount
|
||||
}
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
n.Claims = update(n.Claims)
|
||||
n.Supports = update(n.Supports)
|
||||
n.Claims = update(n.Claims, nil)
|
||||
n.Supports = update(n.Supports, n.SupportSums)
|
||||
return changes
|
||||
}
|
||||
|
||||
|
@ -234,9 +247,9 @@ func (n Node) findBestClaim() *Claim {
|
|||
continue
|
||||
}
|
||||
|
||||
candidateAmount := candidate.EffectiveAmount(n.Supports)
|
||||
if bestAmount <= 0 { // trying to reduce calls to EffectiveAmount
|
||||
bestAmount = best.EffectiveAmount(n.Supports)
|
||||
candidateAmount := candidate.Amount + n.SupportSums[candidate.ClaimID]
|
||||
if bestAmount <= 0 {
|
||||
bestAmount = best.Amount + n.SupportSums[best.ClaimID]
|
||||
}
|
||||
|
||||
switch {
|
||||
|
@ -263,7 +276,7 @@ func (n *Node) activateAllClaims(height int32) int {
|
|||
count := 0
|
||||
for _, c := range n.Claims {
|
||||
if c.Status == Accepted && c.ActiveAt > height && c.VisibleAt <= height {
|
||||
c.setActiveAt(height) // don't necessary need to change this number
|
||||
c.setActiveAt(height) // don't necessarily need to change this number?
|
||||
c.setStatus(Activated)
|
||||
count++
|
||||
}
|
||||
|
@ -271,9 +284,10 @@ func (n *Node) activateAllClaims(height int32) int {
|
|||
|
||||
for _, s := range n.Supports {
|
||||
if s.Status == Accepted && s.ActiveAt > height && s.VisibleAt <= height {
|
||||
s.setActiveAt(height) // don't necessary need to change this number
|
||||
s.setActiveAt(height) // don't necessarily need to change this number?
|
||||
s.setStatus(Activated)
|
||||
count++
|
||||
n.SupportSums[s.ClaimID] += s.Amount
|
||||
}
|
||||
}
|
||||
return count
|
||||
|
@ -283,8 +297,8 @@ func (n *Node) SortClaims() {
|
|||
|
||||
// purposefully sorting by descent
|
||||
sort.Slice(n.Claims, func(j, i int) bool {
|
||||
iAmount := n.Claims[i].EffectiveAmount(n.Supports)
|
||||
jAmount := n.Claims[j].EffectiveAmount(n.Supports)
|
||||
iAmount := n.Claims[i].Amount + n.SupportSums[n.Claims[i].ClaimID]
|
||||
jAmount := n.Claims[j].Amount + n.SupportSums[n.Claims[j].ClaimID]
|
||||
switch {
|
||||
case iAmount < jAmount:
|
||||
return true
|
||||
|
|
|
@ -15,7 +15,7 @@ type Pebble struct {
|
|||
|
||||
func NewPebble(path string) (*Pebble, error) {
|
||||
|
||||
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(128 << 20), BytesPerSync: 16 << 20})
|
||||
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(256 << 20), BytesPerSync: 16 << 20})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue