Skip to content

Commit dd3e8ca

Browse files
committed
use parallel iterate of the storage tables
1 parent cb6bab0 commit dd3e8ca

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

core/state/state_sizer.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"maps"
2424
"slices"
25+
"sync"
2526
"time"
2627

2728
"github.com/ethereum/go-ethereum/common"
@@ -447,8 +448,9 @@ func (t *SizeTracker) build(root common.Hash, blockNumber uint64, done chan buil
447448
return nil
448449
})
449450

451+
// Storage table is huge, iterate in parallel
450452
group.Go(func() error {
451-
count, bytes, err := t.iterateTable(t.abort, rawdb.SnapshotStoragePrefix, "storage")
453+
count, bytes, err := t.iterateTableParallel(t.abort, rawdb.SnapshotStoragePrefix, "storage")
452454
if err != nil {
453455
return err
454456
}
@@ -465,8 +467,9 @@ func (t *SizeTracker) build(root common.Hash, blockNumber uint64, done chan buil
465467
return nil
466468
})
467469

470+
// Storage trienode table is huge, iterate in parallel
468471
group.Go(func() error {
469-
count, bytes, err := t.iterateTable(t.abort, rawdb.TrieNodeStoragePrefix, "storagenode")
472+
count, bytes, err := t.iterateTableParallel(t.abort, rawdb.TrieNodeStoragePrefix, "storagenode")
470473
if err != nil {
471474
return err
472475
}
@@ -531,6 +534,7 @@ func (t *SizeTracker) iterateTable(closed chan struct{}, prefix []byte, name str
531534
logged = time.Now()
532535
count, bytes int64
533536
)
537+
534538
iter := t.db.NewIterator(prefix, nil)
535539
defer iter.Release()
536540

@@ -560,6 +564,44 @@ func (t *SizeTracker) iterateTable(closed chan struct{}, prefix []byte, name str
560564
return count, bytes, nil
561565
}
562566

567+
// iterateTableParallel performs parallel iteration over a table by splitting into hex ranges
568+
// For storage tables, it splits on the first byte of the account hash (after the prefix)
569+
func (t *SizeTracker) iterateTableParallel(closed chan struct{}, prefix []byte, name string) (int64, int64, error) {
570+
var (
571+
start = time.Now()
572+
workers = 16
573+
totalCount int64
574+
totalBytes int64
575+
group errgroup.Group
576+
mu sync.Mutex
577+
)
578+
group.SetLimit(workers)
579+
580+
log.Info("Starting parallel state iteration", "category", name, "workers", workers)
581+
582+
for i := 0; i < 256; i++ {
583+
h := byte(i)
584+
group.Go(func() error {
585+
count, bytes, err := t.iterateTable(closed, slices.Concat(prefix, []byte{h}), fmt.Sprintf("%s-%x", name, h))
586+
if err != nil {
587+
return err
588+
}
589+
mu.Lock()
590+
totalCount += count
591+
totalBytes += bytes
592+
mu.Unlock()
593+
return nil
594+
})
595+
}
596+
597+
if err := group.Wait(); err != nil {
598+
return 0, 0, err
599+
}
600+
601+
log.Info("Finished parallel state iteration", "category", name, "count", totalCount, "size", common.StorageSize(totalBytes), "elapsed", common.PrettyDuration(time.Since(start)))
602+
return totalCount, totalBytes, nil
603+
}
604+
563605
func (t *SizeTracker) upload(stats SizeStats) {
564606
log.Debug("Uploading state size", "number", stats.BlockNumber, "root", stats.StateRoot, "stat", stats)
565607
blockInfoGauge.Update(metrics.GaugeInfoValue{

0 commit comments

Comments
 (0)