diff --git a/claimtrie/node/manager.go b/claimtrie/node/manager.go index d02ef4fe..ebee73bb 100644 --- a/claimtrie/node/manager.go +++ b/claimtrie/node/manager.go @@ -187,7 +187,6 @@ func collectChildNames(changes []change.Change) { // we need to determine which children (names that start with the same name) go with which change // if we have the names in order then we can avoid iterating through all names in the change list // and we can possibly reuse the previous list. - // eh. optimize it some other day // what would happen in the old code: // spending a claim (which happens before every update) could remove a node from the cached trie @@ -213,9 +212,6 @@ func collectChildNames(changes []change.Change) { 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 }) @@ -226,15 +222,16 @@ func collectChildNames(changes []change.Change) { } a := string(changes[i].Name) sc := map[string]bool{} - idx := sort.Search(len(spends), func(i int) bool { - return spends[i].name >= a + idx := sort.Search(len(spends), func(k int) bool { + return spends[k].name > a }) for idx < len(spends) { b := spends[idx].name - if len(b) >= len(a) && spends[idx].order < i && a == b[:len(a)] { + if len(b) <= len(a) || a != b[:len(a)] { + break // since they're ordered alphabetically, we should be able to break out once we're past matches + } + if spends[idx].order < i { sc[b] = true - } else { - break } idx++ } @@ -242,6 +239,29 @@ func collectChildNames(changes []change.Change) { } } +// to understand the above function, it may be helpful to refer to the slower implementation: +//func collectChildNamesSlow(changes []change.Change) { +// for i := range changes { +// t := changes[i].Type +// if t == change.SpendClaim || t == change.SpendSupport { +// continue +// } +// a := 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 +// } +// } +// changes[i].SpentChildren = sc +// } +//} + func (nm *BaseManager) IncrementHeightTo(height int32) ([][]byte, error) { if height <= nm.height { diff --git a/claimtrie/node/manager_test.go b/claimtrie/node/manager_test.go index 48ae1379..6dd61a97 100644 --- a/claimtrie/node/manager_test.go +++ b/claimtrie/node/manager_test.go @@ -236,16 +236,21 @@ func TestCollectChildren(t *testing.T) { 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} + c7 := change.Change{Name: []byte("ab"), Type: change.SpendClaim} + c8 := change.Change{Name: []byte("ab"), Type: change.UpdateClaim} + c := []change.Change{c1, c2, c3, c4, c5, c6, c7, c8} collectChildNames(c) r.Empty(c[0].SpentChildren) r.Empty(c[2].SpentChildren) r.Empty(c[4].SpentChildren) + r.Empty(c[6].SpentChildren) - r.Len(c[1].SpentChildren, 1) - r.Len(c[3].SpentChildren, 1) - r.Len(c[5].SpentChildren, 2) + r.Len(c[1].SpentChildren, 0) + r.Len(c[3].SpentChildren, 0) + r.Len(c[5].SpentChildren, 1) r.True(c[5].SpentChildren["ac"]) + + r.Len(c[7].SpentChildren, 0) }