@@ -22,6 +22,7 @@ import (
22
22
"errors"
23
23
"fmt"
24
24
"math"
25
+ "math/big"
25
26
"os"
26
27
"path/filepath"
27
28
"sync"
@@ -422,54 +423,57 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
422
423
threadStartedAt := time .Now ()
423
424
threadLastLog := time .Now ()
424
425
425
- storageIt , err := storageTr .NodeIterator (nil )
426
+ var processedNodes uint64
427
+ var startStorageIt trie.NodeIterator
428
+ startStorageIt , err = storageTr .NodeIterator (nil )
426
429
if err != nil {
427
430
return
428
431
}
429
- var processedNodes uint64
430
- isNext := true
431
- storageTrieHashes := make ( chan common. Hash , threads )
432
- go func () {
433
- for isNext {
434
- err = <- results
432
+ for i := int64 ( 1 ); i <= 32 ; i ++ {
433
+ // Split the storage trie into 32 parts to parallelize the traversal
434
+ var nextStorageIt trie. NodeIterator
435
+ // For the last iteration, we don't need to create a new iterator, as it will be till the end, so just let it be nil
436
+ if i != 32 {
437
+ nextStorageIt , err = storageTr . NodeIterator ( big . NewInt (( i ) << 3 ). Bytes ())
435
438
if err != nil {
436
439
return
437
440
}
438
- go func () {
439
- threadsRunning .Add (1 )
440
- defer threadsRunning .Add (- 1 )
441
- var err error
442
- defer func () {
443
- results <- err
444
- }()
445
- for storageTrieHash := range storageTrieHashes {
446
- if storageTrieHash != (common.Hash {}) {
447
- // The inner bloomfilter library has a mutex so concurrency is fine here
448
- err = output .Put (storageTrieHash .Bytes (), nil )
449
- if err != nil {
450
- return
451
- }
452
- }
453
- processedNodes ++
454
- if time .Since (threadLastLog ) > 5 * time .Minute {
455
- elapsedTotal := time .Since (startedAt )
456
- elapsedThread := time .Since (threadStartedAt )
457
- log .Info ("traversing trie database - traversing storage trie taking long" , "key" , key , "elapsedTotal" , elapsedTotal , "elapsedThread" , elapsedThread , "processedNodes" , processedNodes , "threadsRunning" , threadsRunning .Load ())
458
- threadLastLog = time .Now ()
441
+ }
442
+ err = <- results
443
+ if err != nil {
444
+ return
445
+ }
446
+ go func (startIt , endIt trie.NodeIterator ) {
447
+ threadsRunning .Add (1 )
448
+ defer threadsRunning .Add (- 1 )
449
+ var err error
450
+ defer func () {
451
+ results <- err
452
+ }()
453
+ // Traverse the storage trie, and stop if we reach the end of the trie or the end of the current part
454
+ for startIt .Next (true ) && (endIt == nil || startIt .Hash () == endIt .Hash ()) {
455
+ storageTrieHash := startIt .Hash ()
456
+ if storageTrieHash != (common.Hash {}) {
457
+ // The inner bloomfilter library has a mutex so concurrency is fine here
458
+ err = output .Put (storageTrieHash .Bytes (), nil )
459
+ if err != nil {
460
+ return
459
461
}
460
462
}
461
- }()
462
- }
463
- }()
464
- for isNext {
465
- isNext = storageIt .Next (true )
466
- storageTrieHash := storageIt .Hash ()
467
- storageTrieHashes <- storageTrieHash
468
- }
469
- close (storageTrieHashes )
470
- err = storageIt .Error ()
471
- if err != nil {
472
- return
463
+ processedNodes ++
464
+ if time .Since (threadLastLog ) > 5 * time .Minute {
465
+ elapsedTotal := time .Since (startedAt )
466
+ elapsedThread := time .Since (threadStartedAt )
467
+ log .Info ("traversing trie database - traversing storage trie taking long" , "key" , key , "elapsedTotal" , elapsedTotal , "elapsedThread" , elapsedThread , "processedNodes" , processedNodes , "threadsRunning" , threadsRunning .Load ())
468
+ threadLastLog = time .Now ()
469
+ }
470
+ }
471
+ err = startIt .Error ()
472
+ if err != nil {
473
+ return
474
+ }
475
+ }(startStorageIt , nextStorageIt )
476
+ startStorageIt = nextStorageIt
473
477
}
474
478
}()
475
479
}
0 commit comments