core, trie: speed up some tests with quadratic processing flaw (#21987)

This commit fixes a flaw in two testcases, and brings down the exec-time from ~40s to ~8s for trie/TestIncompleteSync.

The checkConsistency was performed over and over again on the complete set of nodes, not just the recently added, turning it into a quadratic runtime.
This commit is contained in:
Martin Holst Swende 2020-12-10 14:48:32 +01:00 committed by GitHub
parent 9f6bb492bb
commit b44f24e3e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 21 deletions

@ -62,7 +62,8 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
} }
if i%5 == 0 { if i%5 == 0 {
for j := byte(0); j < 5; j++ { for j := byte(0); j < 5; j++ {
obj.SetState(db, crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j}), crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j})) hash := crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j})
obj.SetState(db, hash, hash)
} }
} }
state.updateStateObject(obj) state.updateStateObject(obj)
@ -401,15 +402,14 @@ func TestIncompleteStateSync(t *testing.T) {
// Create a random state to copy // Create a random state to copy
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
// isCode reports whether the hash is contract code hash. // isCodeLookup to save some hashing
isCode := func(hash common.Hash) bool { var isCode = make(map[common.Hash]struct{})
for _, acc := range srcAccounts { for _, acc := range srcAccounts {
if hash == crypto.Keccak256Hash(acc.code) { if len(acc.code) > 0 {
return true isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
}
} }
return false
} }
isCode[common.BytesToHash(emptyCodeHash)] = struct{}{}
checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot) checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot)
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
@ -447,15 +447,13 @@ func TestIncompleteStateSync(t *testing.T) {
batch.Write() batch.Write()
for _, result := range results { for _, result := range results {
added = append(added, result.Hash) added = append(added, result.Hash)
} // Check that all known sub-tries added so far are complete or missing entirely.
// Check that all known sub-tries added so far are complete or missing entirely. if _, ok := isCode[result.Hash]; ok {
for _, hash := range added {
if isCode(hash) {
continue continue
} }
// Can't use checkStateConsistency here because subtrie keys may have odd // Can't use checkStateConsistency here because subtrie keys may have odd
// length and crash in LeafKey. // length and crash in LeafKey.
if err := checkTrieConsistency(dstDb, hash); err != nil { if err := checkTrieConsistency(dstDb, result.Hash); err != nil {
t.Fatalf("state inconsistent: %v", err) t.Fatalf("state inconsistent: %v", err)
} }
} }
@ -466,9 +464,9 @@ func TestIncompleteStateSync(t *testing.T) {
// Sanity check that removing any node from the database is detected // Sanity check that removing any node from the database is detected
for _, node := range added[1:] { for _, node := range added[1:] {
var ( var (
key = node.Bytes() key = node.Bytes()
code = isCode(node) _, code = isCode[node]
val []byte val []byte
) )
if code { if code {
val = rawdb.ReadCode(dstDb, node) val = rawdb.ReadCode(dstDb, node)

@ -377,7 +377,6 @@ func TestIncompleteSync(t *testing.T) {
nodes, _, codes := sched.Missing(1) nodes, _, codes := sched.Missing(1)
queue := append(append([]common.Hash{}, nodes...), codes...) queue := append(append([]common.Hash{}, nodes...), codes...)
for len(queue) > 0 { for len(queue) > 0 {
// Fetch a batch of trie nodes // Fetch a batch of trie nodes
results := make([]SyncResult, len(queue)) results := make([]SyncResult, len(queue))
@ -401,10 +400,8 @@ func TestIncompleteSync(t *testing.T) {
batch.Write() batch.Write()
for _, result := range results { for _, result := range results {
added = append(added, result.Hash) added = append(added, result.Hash)
} // Check that all known sub-tries in the synced trie are complete
// Check that all known sub-tries in the synced trie are complete if err := checkTrieConsistency(triedb, result.Hash); err != nil {
for _, root := range added {
if err := checkTrieConsistency(triedb, root); err != nil {
t.Fatalf("trie inconsistent: %v", err) t.Fatalf("trie inconsistent: %v", err)
} }
} }