Skip to content

Commit d2f04dd

Browse files
committed
fix
1 parent 43b8488 commit d2f04dd

File tree

1 file changed

+38
-22
lines changed

1 file changed

+38
-22
lines changed

core/state/pruner/pruner.go

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
371371
for i := 0; i < threads; i++ {
372372
results <- nil
373373
}
374+
// We also create a semaphore for the storage trie traversal, to limit the number of goroutines
375+
resultsPerAccount := make(chan error, threads)
376+
for i := 0; i < threads; i++ {
377+
resultsPerAccount <- nil
378+
}
374379
var threadsRunning atomic.Int32
375380

376381
for accountIt.Next(true) {
@@ -424,38 +429,33 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
424429
threadLastLog := time.Now()
425430

426431
var processedNodes uint64
427-
var startStorageIt trie.NodeIterator
428-
startStorageIt, err = storageTr.NodeIterator(nil)
429-
if err != nil {
430-
return
431-
}
432432
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-
var nextStorageItHash common.Hash
436-
// 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
437-
if i != 32 {
438-
nextStorageIt, err = storageTr.NodeIterator(big.NewInt((i) << 3).Bytes())
439-
nextStorageItHash = nextStorageIt.Hash()
440-
if err != nil {
441-
return
442-
}
443-
}
444-
err = <-results
433+
err = <-resultsPerAccount
445434
if err != nil {
446435
return
447436
}
448-
go func(startIt trie.NodeIterator, endHash common.Hash) {
437+
go func(iteration int64) {
449438
threadsRunning.Add(1)
450439
defer threadsRunning.Add(-1)
451440
var err error
452441
defer func() {
453-
results <- err
442+
resultsPerAccount <- err
454443
}()
444+
var startIt trie.NodeIterator
445+
startIt, err = storageTr.NodeIterator(big.NewInt((i - 1) << 3).Bytes())
446+
if err != nil {
447+
return
448+
}
449+
455450
// Traverse the storage trie, and stop if we reach the end of the trie or the end of the current part
456451
var startItPath, endItPath []byte
457452

458-
for startIt.Next(true) && (endHash == common.Hash{} || endHash.Cmp(startIt.Hash()) != 0) {
453+
key := keybytesToHex(big.NewInt((iteration) << 3).Bytes())
454+
key = key[:len(key)-1]
455+
for startIt.Next(true) {
456+
if iteration != 32 && bytes.Compare(startIt.Path(), key) >= 0 {
457+
break
458+
}
459459
if startItPath == nil {
460460
startItPath = startIt.Path()
461461
}
@@ -481,8 +481,7 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
481481
return
482482
}
483483
log.Trace("Finished traversing storage trie", "key", key, "startPath", startItPath, "endPath", endItPath)
484-
}(startStorageIt, nextStorageItHash)
485-
startStorageIt = nextStorageIt
484+
}(i)
486485
}
487486
}()
488487
}
@@ -497,9 +496,26 @@ func dumpRawTrieDescendants(db ethdb.Database, root common.Hash, output *stateBl
497496
return err
498497
}
499498
}
499+
for i := 0; i < threads; i++ {
500+
err = <-resultsPerAccount
501+
if err != nil {
502+
return err
503+
}
504+
}
500505
return nil
501506
}
502507

508+
func keybytesToHex(str []byte) []byte {
509+
l := len(str)*2 + 1
510+
var nibbles = make([]byte, l)
511+
for i, b := range str {
512+
nibbles[i*2] = b / 16
513+
nibbles[i*2+1] = b % 16
514+
}
515+
nibbles[l-1] = 16
516+
return nibbles
517+
}
518+
503519
// Prune deletes all historical state nodes except the nodes belong to the
504520
// specified state version. If user doesn't specify the state version, use
505521
// the bottom-most snapshot diff layer as the target.

0 commit comments

Comments
 (0)