@@ -27,8 +27,8 @@ import (
2727 "golang.org/x/sync/errgroup"
2828)
2929
30- // storageNodesShardCount is the number of shards used for storage nodes.
31- const storageNodesShardCount = 16
30+ // trienodeShardCount is the number of shards used for trie nodes.
31+ const trienodeShardCount = 16
3232
3333// storageKey returns a key for uniquely identifying the storage slot.
3434func storageKey (accountHash common.Hash , slotHash common.Hash ) [64 ]byte {
@@ -71,30 +71,31 @@ type lookup struct {
7171 storages map [[64 ]byte ][]common.Hash
7272
7373 // accountNodes represents the mutation history for specific account
74- // trie nodes. The key is the trie path of the node, and the value is a slice
74+ // trie nodes, distributed across 16 shards for efficiency.
75+ // The key is the trie path of the node, and the value is a slice
7576 // of **diff layer** IDs indicating where the account was modified,
7677 // with the order from oldest to newest.
77- accountNodes map [string ][]common.Hash
78+ accountNodes [ trienodeShardCount ] map [string ][]common.Hash
7879
7980 // storageNodes represents the mutation history for specific storage
8081 // slot trie nodes, distributed across 16 shards for efficiency.
8182 // The key is the account address hash and the trie path of the node,
8283 // the value is a slice of **diff layer** IDs indicating where the
8384 // slot was modified, with the order from oldest to newest.
84- storageNodes [storageNodesShardCount ]map [trienodeKey ][]common.Hash
85+ storageNodes [trienodeShardCount ]map [trienodeKey ][]common.Hash
8586
8687 // descendant is the callback indicating whether the layer with
8788 // given root is a descendant of the one specified by `ancestor`.
8889 descendant func (state common.Hash , ancestor common.Hash ) bool
8990}
9091
91- // getStorageShardIndex returns the shard index for a given path
92- func getStorageShardIndex (path string ) int {
92+ // getNodeShardIndex returns the shard index for a given path
93+ func getNodeShardIndex (path string ) int {
9394 if len (path ) == 0 {
9495 return 0
9596 }
9697 // use the first char of the path to determine the shard index
97- return int (path [0 ]) % storageNodesShardCount
98+ return int (path [0 ]) % trienodeShardCount
9899}
99100
100101// newLookup initializes the lookup structure.
@@ -108,14 +109,14 @@ func newLookup(head layer, descendant func(state common.Hash, ancestor common.Ha
108109 current = current .parentLayer ()
109110 }
110111 l := & lookup {
111- accounts : make (map [common.Hash ][]common.Hash ),
112- storages : make (map [[64 ]byte ][]common.Hash ),
113- accountNodes : make (map [string ][]common.Hash ),
114- descendant : descendant ,
112+ accounts : make (map [common.Hash ][]common.Hash ),
113+ storages : make (map [[64 ]byte ][]common.Hash ),
114+ descendant : descendant ,
115115 }
116116 // Initialize all 16 storage node shards
117- for i := 0 ; i < storageNodesShardCount ; i ++ {
117+ for i := 0 ; i < trienodeShardCount ; i ++ {
118118 l .storageNodes [i ] = make (map [trienodeKey ][]common.Hash )
119+ l .accountNodes [i ] = make (map [string ][]common.Hash )
119120 }
120121
121122 // Apply the diff layers from bottom to top
@@ -225,9 +226,10 @@ func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, state
225226func (l * lookup ) nodeTip (accountHash common.Hash , path string , stateID common.Hash , base common.Hash ) common.Hash {
226227 var list []common.Hash
227228 if accountHash == (common.Hash {}) {
228- list = l .accountNodes [path ]
229+ shardIndex := getNodeShardIndex (path )
230+ list = l.accountNodes [shardIndex ][path ]
229231 } else {
230- shardIndex := getStorageShardIndex (path ) // Use only path for sharding
232+ shardIndex := getNodeShardIndex (path ) // Use only path for sharding
231233 list = l .storageNodes [shardIndex ][makeTrienodeKey (accountHash , path )]
232234 }
233235 for i := len (list ) - 1 ; i >= 0 ; i -- {
@@ -297,14 +299,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
297299 wg .Add (1 )
298300 go func () {
299301 defer wg .Done ()
300- for path := range diff .nodes .accountNodes {
301- list , exists := l .accountNodes [path ]
302- if ! exists {
303- list = make ([]common.Hash , 0 , 16 ) // TODO(rjl493456442) use sync pool
304- }
305- list = append (list , state )
306- l .accountNodes [path ] = list
307- }
302+ l .addAccountNodes (state , diff .nodes .accountNodes )
308303 }()
309304
310305 wg .Add (1 )
@@ -335,43 +330,61 @@ func (l *lookup) addStorageNodes(state common.Hash, nodes map[common.Hash]map[st
335330
336331 var (
337332 wg sync.WaitGroup
338- tasks = make ([][]shardTask , storageNodesShardCount )
333+ tasks = make ([][]shardTask , trienodeShardCount )
339334 )
340-
341- // Pre-allocate work lists
342335 for accountHash , slots := range nodes {
343336 for path := range slots {
344- shardIndex := getStorageShardIndex (path )
337+ shardIndex := getNodeShardIndex (path )
345338 tasks [shardIndex ] = append (tasks [shardIndex ], shardTask {
346339 accountHash : accountHash ,
347340 path : path ,
348341 })
349342 }
350343 }
351-
352- // Start all workers, each handling its own shard
353- wg .Add (storageNodesShardCount )
354- for shardIndex := 0 ; shardIndex < storageNodesShardCount ; shardIndex ++ {
355- go func (shardIdx int ) {
344+ for shardIdx := 0 ; shardIdx < trienodeShardCount ; shardIdx ++ {
345+ taskList := tasks [shardIdx ]
346+ if len (taskList ) == 0 {
347+ continue
348+ }
349+ wg .Add (1 )
350+ go func () {
356351 defer wg .Done ()
357-
358- taskList := tasks [shardIdx ]
359- if len (taskList ) == 0 {
360- return
361- }
362-
363352 shard := l .storageNodes [shardIdx ]
364353 for _ , task := range taskList {
365354 key := makeTrienodeKey (task .accountHash , task .path )
366- list , exists := shard [key ]
367- if ! exists {
368- list = make ([]common.Hash , 0 , 16 ) // TODO(rjl493456442) use sync pool
369- }
370- list = append (list , state )
371- shard [key ] = list
355+ shard [key ] = append (shard [key ], state )
372356 }
357+ }()
358+ }
359+ wg .Wait ()
360+ }
373361
374- }(shardIndex )
362+ func (l * lookup ) addAccountNodes (state common.Hash , nodes map [string ]* trienode.Node ) {
363+ defer func (start time.Time ) {
364+ lookupAddTrienodeLayerTimer .UpdateSince (start )
365+ }(time .Now ())
366+
367+ var (
368+ wg sync.WaitGroup
369+ tasks = make ([][]string , trienodeShardCount )
370+ )
371+ for path := range nodes {
372+ shardIndex := getNodeShardIndex (path )
373+ tasks [shardIndex ] = append (tasks [shardIndex ], path )
374+ }
375+ for shardIdx := 0 ; shardIdx < trienodeShardCount ; shardIdx ++ {
376+ taskList := tasks [shardIdx ]
377+ if len (taskList ) == 0 {
378+ continue
379+ }
380+ wg .Add (1 )
381+ go func () {
382+ defer wg .Done ()
383+ shard := l .accountNodes [shardIdx ]
384+ for _ , path := range taskList {
385+ shard [path ] = append (shard [path ], state )
386+ }
387+ }()
375388 }
376389 wg .Wait ()
377390}
@@ -446,18 +459,7 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
446459 })
447460
448461 eg .Go (func () error {
449- for path := range diff .nodes .accountNodes {
450- found , list := removeFromList (l .accountNodes [path ], state )
451- if ! found {
452- return fmt .Errorf ("account lookup is not found, %x, state: %x" , path , state )
453- }
454- if len (list ) != 0 {
455- l .accountNodes [path ] = list
456- } else {
457- delete (l .accountNodes , path )
458- }
459- }
460- return nil
462+ return l .removeAccountNodes (state , diff .nodes .accountNodes )
461463 })
462464
463465 eg .Go (func () error {
@@ -473,29 +475,23 @@ func (l *lookup) removeStorageNodes(state common.Hash, nodes map[common.Hash]map
473475
474476 var (
475477 eg errgroup.Group
476- tasks = make ([][]shardTask , storageNodesShardCount )
478+ tasks = make ([][]shardTask , trienodeShardCount )
477479 )
478-
479- // Pre-allocate work lists
480480 for accountHash , slots := range nodes {
481481 for path := range slots {
482- shardIndex := getStorageShardIndex (path )
482+ shardIndex := getNodeShardIndex (path )
483483 tasks [shardIndex ] = append (tasks [shardIndex ], shardTask {
484484 accountHash : accountHash ,
485485 path : path ,
486486 })
487487 }
488488 }
489-
490- // Start all workers, each handling its own shard
491- for shardIndex := 0 ; shardIndex < storageNodesShardCount ; shardIndex ++ {
492- shardIdx := shardIndex // Capture the variable
489+ for shardIdx := 0 ; shardIdx < trienodeShardCount ; shardIdx ++ {
490+ taskList := tasks [shardIdx ]
491+ if len (taskList ) == 0 {
492+ continue
493+ }
493494 eg .Go (func () error {
494- taskList := tasks [shardIdx ]
495- if len (taskList ) == 0 {
496- return nil
497- }
498-
499495 shard := l .storageNodes [shardIdx ]
500496 for _ , task := range taskList {
501497 key := makeTrienodeKey (task .accountHash , task .path )
@@ -514,3 +510,40 @@ func (l *lookup) removeStorageNodes(state common.Hash, nodes map[common.Hash]map
514510 }
515511 return eg .Wait ()
516512}
513+
514+ func (l * lookup ) removeAccountNodes (state common.Hash , nodes map [string ]* trienode.Node ) error {
515+ defer func (start time.Time ) {
516+ lookupRemoveTrienodeLayerTimer .UpdateSince (start )
517+ }(time .Now ())
518+
519+ var (
520+ eg errgroup.Group
521+ tasks = make ([][]string , trienodeShardCount )
522+ )
523+ for path := range nodes {
524+ shardIndex := getNodeShardIndex (path )
525+ tasks [shardIndex ] = append (tasks [shardIndex ], path )
526+ }
527+ for shardIdx := 0 ; shardIdx < trienodeShardCount ; shardIdx ++ {
528+ taskList := tasks [shardIdx ]
529+ if len (taskList ) == 0 {
530+ continue
531+ }
532+ eg .Go (func () error {
533+ shard := l .accountNodes [shardIdx ]
534+ for _ , path := range taskList {
535+ found , list := removeFromList (shard [path ], state )
536+ if ! found {
537+ return fmt .Errorf ("account lookup is not found, %x, state: %x" , path , state )
538+ }
539+ if len (list ) != 0 {
540+ shard [path ] = list
541+ } else {
542+ delete (shard , path )
543+ }
544+ }
545+ return nil
546+ })
547+ }
548+ return eg .Wait ()
549+ }
0 commit comments