optimize collectSpentChildren, add tests for it
This commit is contained in:
parent
88dbf2267c
commit
e8b2910b36
5 changed files with 150 additions and 11 deletions
|
@ -354,6 +354,7 @@ func (ct *ClaimTrie) Close() {
|
|||
node.LogOnce("On cleanup: " + err.Error())
|
||||
}
|
||||
}
|
||||
ct.cleanups = nil
|
||||
}
|
||||
|
||||
func (ct *ClaimTrie) forwardNodeChange(chg change.Change) error {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package claimtrie
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/claimtrie/change"
|
||||
"github.com/btcsuite/btcd/claimtrie/config"
|
||||
|
@ -252,3 +254,94 @@ func TestRebuild(t *testing.T) {
|
|||
r.NotNil(m2)
|
||||
r.Equal(*m, *m2)
|
||||
}
|
||||
|
||||
func BenchmarkClaimTrie_AppendBlock(b *testing.B) {
|
||||
|
||||
rand.Seed(42)
|
||||
names := make([][]byte, 0, b.N)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
names = append(names, randomName())
|
||||
}
|
||||
|
||||
param.SetNetwork(wire.TestNet)
|
||||
param.OriginalClaimExpirationTime = 1000000
|
||||
param.ExtendedClaimExpirationTime = 1000000
|
||||
cfg.DataDir = b.TempDir()
|
||||
|
||||
r := require.New(b)
|
||||
ct, err := New(cfg)
|
||||
r.NoError(err)
|
||||
defer ct.Close()
|
||||
h1 := chainhash.Hash{100, 200}
|
||||
|
||||
start := time.Now()
|
||||
b.ResetTimer()
|
||||
|
||||
c := 0
|
||||
for i := 0; i < b.N; i++ {
|
||||
op := wire.OutPoint{Hash: h1, Index: uint32(i)}
|
||||
id := change.NewClaimID(op)
|
||||
err = ct.AddClaim(names[i], op, id, 500)
|
||||
r.NoError(err)
|
||||
if c++; (c & 0xff) == 0xff {
|
||||
err = ct.AppendBlock()
|
||||
r.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
op := wire.OutPoint{Hash: h1, Index: uint32(i)}
|
||||
id := change.NewClaimID(op)
|
||||
op.Hash[0] = 1
|
||||
err = ct.UpdateClaim(names[i], op, 400, id)
|
||||
r.NoError(err)
|
||||
if c++; (c & 0xff) == 0xff {
|
||||
err = ct.AppendBlock()
|
||||
r.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
op := wire.OutPoint{Hash: h1, Index: uint32(i)}
|
||||
id := change.NewClaimID(op)
|
||||
op.Hash[0] = 2
|
||||
err = ct.UpdateClaim(names[i], op, 300, id)
|
||||
r.NoError(err)
|
||||
if c++; (c & 0xff) == 0xff {
|
||||
err = ct.AppendBlock()
|
||||
r.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
op := wire.OutPoint{Hash: h1, Index: uint32(i)}
|
||||
id := change.NewClaimID(op)
|
||||
op.Hash[0] = 3
|
||||
err = ct.SpendClaim(names[i], op, id)
|
||||
r.NoError(err)
|
||||
if c++; (c & 0xff) == 0xff {
|
||||
err = ct.AppendBlock()
|
||||
r.NoError(err)
|
||||
}
|
||||
}
|
||||
err = ct.AppendBlock()
|
||||
r.NoError(err)
|
||||
|
||||
b.StopTimer()
|
||||
ht := ct.height
|
||||
h1 = *ct.MerkleHash()
|
||||
ct.Close()
|
||||
b.Logf("Running AppendBlock bench with %d names in %f sec. Height: %d, Hash: %s",
|
||||
b.N, time.Since(start).Seconds(), ht, h1.String())
|
||||
}
|
||||
|
||||
func randomName() []byte {
|
||||
name := make([]byte, rand.Intn(30)+10)
|
||||
rand.Read(name)
|
||||
for i := range name {
|
||||
name[i] %= 56
|
||||
name[i] += 65
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ func (rt *RamTrie) merkleHashAllClaims(v *collapsedVertex) *chainhash.Hash {
|
|||
if v.claimHash != nil {
|
||||
claimHash = v.claimHash
|
||||
} else if len(childHashes) == 0 {
|
||||
return v.merkleHash
|
||||
return nil
|
||||
}
|
||||
|
||||
childHash := NoChildrenHash
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package node
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -199,22 +199,44 @@ func collectChildNames(changes []change.Change) {
|
|||
// For each non-spend change
|
||||
// Loop through all the spends before you and add them to your child list if they are your child
|
||||
|
||||
type pair struct {
|
||||
name string
|
||||
order int
|
||||
}
|
||||
|
||||
spends := make([]pair, 0, len(changes))
|
||||
for i := range changes {
|
||||
t := changes[i].Type
|
||||
if t != change.SpendClaim {
|
||||
continue
|
||||
}
|
||||
spends = append(spends, pair{string(changes[i].Name), i})
|
||||
}
|
||||
sort.Slice(spends, func(i, j int) bool {
|
||||
if spends[i].name == spends[j].name {
|
||||
return spends[i].order < spends[j].order
|
||||
}
|
||||
return spends[i].name < spends[j].name
|
||||
})
|
||||
|
||||
for i := range changes {
|
||||
t := changes[i].Type
|
||||
if t == change.SpendClaim || t == change.SpendSupport {
|
||||
continue
|
||||
}
|
||||
a := changes[i].Name
|
||||
a := string(changes[i].Name)
|
||||
sc := map[string]bool{}
|
||||
for j := 0; j < i; j++ {
|
||||
t = changes[j].Type
|
||||
if t != change.SpendClaim {
|
||||
continue
|
||||
}
|
||||
b := changes[j].Name
|
||||
if len(b) >= len(a) && bytes.Equal(a, b[:len(a)]) {
|
||||
sc[string(b)] = true
|
||||
idx := sort.Search(len(spends), func(i int) bool {
|
||||
return spends[i].name >= a
|
||||
})
|
||||
for idx < len(spends) {
|
||||
b := spends[idx].name
|
||||
if len(b) >= len(a) && spends[idx].order < i && a == b[:len(a)] {
|
||||
sc[b] = true
|
||||
} else {
|
||||
break
|
||||
}
|
||||
idx++
|
||||
}
|
||||
changes[i].SpentChildren = sc
|
||||
}
|
||||
|
|
|
@ -226,3 +226,26 @@ func TestHasChildren(t *testing.T) {
|
|||
r.NoError(err)
|
||||
r.True(m.hasChildren([]byte("a"), 4, nil, 2))
|
||||
}
|
||||
|
||||
func TestCollectChildren(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
c1 := change.Change{Name: []byte("ba"), Type: change.SpendClaim}
|
||||
c2 := change.Change{Name: []byte("ba"), Type: change.UpdateClaim}
|
||||
c3 := change.Change{Name: []byte("ac"), Type: change.SpendClaim}
|
||||
c4 := change.Change{Name: []byte("ac"), Type: change.UpdateClaim}
|
||||
c5 := change.Change{Name: []byte("a"), Type: change.SpendClaim}
|
||||
c6 := change.Change{Name: []byte("a"), Type: change.UpdateClaim}
|
||||
c := []change.Change{c1, c2, c3, c4, c5, c6}
|
||||
|
||||
collectChildNames(c)
|
||||
|
||||
r.Empty(c[0].SpentChildren)
|
||||
r.Empty(c[2].SpentChildren)
|
||||
r.Empty(c[4].SpentChildren)
|
||||
|
||||
r.Len(c[1].SpentChildren, 1)
|
||||
r.Len(c[3].SpentChildren, 1)
|
||||
r.Len(c[5].SpentChildren, 2)
|
||||
r.True(c[5].SpentChildren["ac"])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue