mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-08-23 17:47:24 +00:00
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/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"runtime"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClaimTrie implements a Merkle Trie supporting linear history of commits.
|
// 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)
|
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{
|
ct := &ClaimTrie{
|
||||||
blockRepo: blockRepo,
|
blockRepo: blockRepo,
|
||||||
temporalRepo: temporalRepo,
|
temporalRepo: temporalRepo,
|
||||||
|
@ -149,6 +139,25 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
}
|
}
|
||||||
ct.cleanups = cleanups
|
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
|
return ct, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@ func showClaim(c *node.Claim, n *node.Node) {
|
||||||
mark = "*"
|
mark = "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s C ID: %s, TXO: %s\n %5d/%-5d, Status: %9s, Amount: %15d, Effective Amount: %15d\n",
|
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, c.EffectiveAmount(n.Supports))
|
mark, c.ClaimID, c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount, n.SupportSums[c.ClaimID])
|
||||||
}
|
}
|
||||||
|
|
||||||
func showSupport(c *node.Claim) {
|
func showSupport(c *node.Claim) {
|
||||||
|
|
|
@ -101,23 +101,6 @@ func (c *Claim) setStatus(status Status) *Claim {
|
||||||
return c
|
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 {
|
func (c *Claim) ExpireAt() int32 {
|
||||||
|
|
||||||
if c.AcceptedAt+param.OriginalClaimExpirationTime > param.ExtendedClaimExpirationForkHeight {
|
if c.AcceptedAt+param.OriginalClaimExpirationTime > param.ExtendedClaimExpirationForkHeight {
|
||||||
|
|
|
@ -16,6 +16,7 @@ var (
|
||||||
out1 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:1")
|
out1 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:1")
|
||||||
out2 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:2")
|
out2 = NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:2")
|
||||||
out3 = NewOutPointFromString("0100000000000000000000000000000000000000000000000000000000000000:1")
|
out3 = NewOutPointFromString("0100000000000000000000000000000000000000000000000000000000000000:1")
|
||||||
|
out4 = NewOutPointFromString("0100000000000000000000000000000000000000000000000000000000000000:2")
|
||||||
name1 = []byte("name1")
|
name1 = []byte("name1")
|
||||||
name2 = []byte("name2")
|
name2 = []byte("name2")
|
||||||
)
|
)
|
||||||
|
@ -51,6 +52,7 @@ func TestSimpleAddClaim(t *testing.T) {
|
||||||
|
|
||||||
m, err := NewBaseManager(repo)
|
m, err := NewBaseManager(repo)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
defer m.Close()
|
||||||
|
|
||||||
_, err = m.IncrementHeightTo(10)
|
_, err = m.IncrementHeightTo(10)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
@ -90,6 +92,58 @@ func TestSimpleAddClaim(t *testing.T) {
|
||||||
r.Nil(n2)
|
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) {
|
func TestNodeSort(t *testing.T) {
|
||||||
|
|
||||||
r := require.New(t)
|
r := require.New(t)
|
||||||
|
|
|
@ -17,11 +17,12 @@ type Node struct {
|
||||||
TakenOverAt int32 // The height at when the current BestClaim took over.
|
TakenOverAt int32 // The height at when the current BestClaim took over.
|
||||||
Claims ClaimList // List of all Claims.
|
Claims ClaimList // List of all Claims.
|
||||||
Supports ClaimList // List of all Supports, including orphaned ones.
|
Supports ClaimList // List of all Supports, including orphaned ones.
|
||||||
|
SupportSums map[string]int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new node.
|
// New returns a new node.
|
||||||
func New() *Node {
|
func New() *Node {
|
||||||
return &Node{}
|
return &Node{SupportSums: map[string]int64{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
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:
|
case change.SpendSupport:
|
||||||
s := n.Supports.find(byOut(*out))
|
s := n.Supports.find(byOut(*out))
|
||||||
if s != nil {
|
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)
|
s.setStatus(Deactivated)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Spending support but missing existing support with TXO %s\n "+
|
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 {
|
func (n *Node) handleExpiredAndActivated(height int32) int {
|
||||||
|
|
||||||
changes := 0
|
changes := 0
|
||||||
update := func(items ClaimList) ClaimList {
|
update := func(items ClaimList, sums map[string]int64) ClaimList {
|
||||||
for i := 0; i < len(items); i++ {
|
for i := 0; i < len(items); i++ {
|
||||||
c := items[i]
|
c := items[i]
|
||||||
if c.Status == Accepted && c.ActiveAt <= height && c.VisibleAt <= height {
|
if c.Status == Accepted && c.ActiveAt <= height && c.VisibleAt <= height {
|
||||||
c.setStatus(Activated)
|
c.setStatus(Activated)
|
||||||
changes++
|
changes++
|
||||||
|
if sums != nil {
|
||||||
|
sums[c.ClaimID] += c.Amount
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if c.ExpireAt() <= height || c.Status == Deactivated {
|
if c.ExpireAt() <= height || c.Status == Deactivated {
|
||||||
if i < len(items)-1 {
|
if i < len(items)-1 {
|
||||||
|
@ -165,12 +175,15 @@ func (n *Node) handleExpiredAndActivated(height int32) int {
|
||||||
}
|
}
|
||||||
items = items[:len(items)-1]
|
items = items[:len(items)-1]
|
||||||
changes++
|
changes++
|
||||||
|
if sums != nil && c.Status != Deactivated {
|
||||||
|
sums[c.ClaimID] -= c.Amount
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
n.Claims = update(n.Claims)
|
n.Claims = update(n.Claims, nil)
|
||||||
n.Supports = update(n.Supports)
|
n.Supports = update(n.Supports, n.SupportSums)
|
||||||
return changes
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,9 +247,9 @@ func (n Node) findBestClaim() *Claim {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
candidateAmount := candidate.EffectiveAmount(n.Supports)
|
candidateAmount := candidate.Amount + n.SupportSums[candidate.ClaimID]
|
||||||
if bestAmount <= 0 { // trying to reduce calls to EffectiveAmount
|
if bestAmount <= 0 {
|
||||||
bestAmount = best.EffectiveAmount(n.Supports)
|
bestAmount = best.Amount + n.SupportSums[best.ClaimID]
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -263,7 +276,7 @@ func (n *Node) activateAllClaims(height int32) int {
|
||||||
count := 0
|
count := 0
|
||||||
for _, c := range n.Claims {
|
for _, c := range n.Claims {
|
||||||
if c.Status == Accepted && c.ActiveAt > height && c.VisibleAt <= height {
|
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)
|
c.setStatus(Activated)
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
@ -271,9 +284,10 @@ func (n *Node) activateAllClaims(height int32) int {
|
||||||
|
|
||||||
for _, s := range n.Supports {
|
for _, s := range n.Supports {
|
||||||
if s.Status == Accepted && s.ActiveAt > height && s.VisibleAt <= height {
|
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)
|
s.setStatus(Activated)
|
||||||
count++
|
count++
|
||||||
|
n.SupportSums[s.ClaimID] += s.Amount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
|
@ -283,8 +297,8 @@ func (n *Node) SortClaims() {
|
||||||
|
|
||||||
// purposefully sorting by descent
|
// purposefully sorting by descent
|
||||||
sort.Slice(n.Claims, func(j, i int) bool {
|
sort.Slice(n.Claims, func(j, i int) bool {
|
||||||
iAmount := n.Claims[i].EffectiveAmount(n.Supports)
|
iAmount := n.Claims[i].Amount + n.SupportSums[n.Claims[i].ClaimID]
|
||||||
jAmount := n.Claims[j].EffectiveAmount(n.Supports)
|
jAmount := n.Claims[j].Amount + n.SupportSums[n.Claims[j].ClaimID]
|
||||||
switch {
|
switch {
|
||||||
case iAmount < jAmount:
|
case iAmount < jAmount:
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -15,7 +15,7 @@ type Pebble struct {
|
||||||
|
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue