-
Notifications
You must be signed in to change notification settings - Fork 0
trie/metrics: Adding state depth metrics tracking using witness #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: state-size-metrics
Are you sure you want to change the base?
Changes from all commits
36853ae
e036f75
6bddb84
3a93dd3
ca230df
b6ac715
f78a59e
530148c
1922af5
1549efc
ed574d1
8be634d
435c063
87e1d82
bfbd917
7f015f3
6a546b9
09375fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -112,6 +112,9 @@ var ( | |
| errChainStopped = errors.New("blockchain is stopped") | ||
| errInvalidOldChain = errors.New("invalid old chain") | ||
| errInvalidNewChain = errors.New("invalid new chain") | ||
|
|
||
| avgAccessDepthInBlock = metrics.NewRegisteredGauge("trie/access/depth/avg", nil) | ||
| minAccessDepthInBlock = metrics.NewRegisteredGauge("trie/access/depth/min", nil) | ||
| ) | ||
|
|
||
| var ( | ||
|
|
@@ -331,6 +334,8 @@ type BlockChain struct { | |
| processor Processor // Block transaction processor interface | ||
| logger *tracing.Hooks | ||
|
|
||
| stateSizeGen *state.StateSizeGenerator // State size tracking | ||
|
|
||
| lastForkReadyAlert time.Time // Last time there was a fork readiness print out | ||
| } | ||
|
|
||
|
|
@@ -523,6 +528,11 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, | |
| if bc.cfg.TxLookupLimit >= 0 { | ||
| bc.txIndexer = newTxIndexer(uint64(bc.cfg.TxLookupLimit), bc) | ||
| } | ||
|
|
||
| // Start state size tracker | ||
| bc.stateSizeGen = state.NewStateSizeGenerator(bc.statedb.DiskDB(), bc.triedb, head.Root) | ||
| log.Info("Started state size generator", "root", head.Root) | ||
|
|
||
| return bc, nil | ||
| } | ||
|
|
||
|
|
@@ -1249,6 +1259,12 @@ func (bc *BlockChain) stopWithoutSaving() { | |
| // Signal shutdown to all goroutines. | ||
| bc.InterruptInsert(true) | ||
|
|
||
| // Stop state size generator if running | ||
| if bc.stateSizeGen != nil { | ||
| bc.stateSizeGen.Stop() | ||
| log.Info("Stopped state size generator") | ||
| } | ||
|
|
||
| // Now wait for all chain modifications to end and persistent goroutines to exit. | ||
| // | ||
| // Note: Close waits for the mutex to become available, i.e. any running chain | ||
|
|
@@ -1310,6 +1326,7 @@ func (bc *BlockChain) Stop() { | |
| } | ||
| } | ||
| } | ||
|
|
||
| // Allow tracers to clean-up and release resources. | ||
| if bc.logger != nil && bc.logger.OnClose != nil { | ||
| bc.logger.OnClose() | ||
|
|
@@ -1583,10 +1600,15 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. | |
| log.Crit("Failed to write block into disk", "err", err) | ||
| } | ||
| // Commit all cached state changes into underlying memory database. | ||
| root, err := statedb.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time())) | ||
| root, stateUpdate, err := statedb.CommitWithUpdate(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time())) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // Track state size changes if generator is running | ||
| if bc.stateSizeGen != nil && stateUpdate != nil { | ||
| bc.stateSizeGen.Track(stateUpdate) | ||
| } | ||
| // If node is running in path mode, skip explicit gc operation | ||
| // which is unnecessary in this mode. | ||
| if bc.triedb.Scheme() == rawdb.PathScheme { | ||
|
|
@@ -2083,6 +2105,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s | |
| return nil, fmt.Errorf("stateless self-validation receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, block.ReceiptHash()) | ||
| } | ||
| } | ||
|
|
||
| xvtime := time.Since(xvstart) | ||
| proctime := time.Since(startTime) // processing + validation + cross validation | ||
|
|
||
|
|
@@ -2118,6 +2141,24 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s | |
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // If witness was generated, update metrics regarding the access paths. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note for later: this is creating a dependency on the witness creation, so maybe it would be a good idea to create a specific object that is passed to |
||
| if witness != nil { | ||
| paths := witness.Paths | ||
| totaldepth, pathnum, mindepth := 0, 0, -1 | ||
| if len(paths) > 0 { | ||
| for path, _ := range paths { | ||
| if len(path) < mindepth || mindepth < 0 { | ||
| mindepth = len(path) | ||
| } | ||
| totaldepth += len(path) | ||
| pathnum++ | ||
| } | ||
| avgAccessDepthInBlock.Update(int64(totaldepth) / int64(pathnum)) | ||
| minAccessDepthInBlock.Update(int64(mindepth)) | ||
| } | ||
| } | ||
|
|
||
| // Update the metrics touched during block commit | ||
| accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them | ||
| storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -124,6 +124,10 @@ type Trie interface { | |||||
| // The returned map could be nil if the witness is empty. | ||||||
| Witness() map[string]struct{} | ||||||
|
|
||||||
| // WitnessPaths returns a set of paths for all trie nodes. For future reference, | ||||||
| // witness can be deprecated and used as a replacement to witness. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree with this comment, because the witness will be spec'd by something exterior and this external consumer will not be interested in the paths because of size reasons. But we shall see. |
||||||
| WitnessPaths() map[string]struct{} | ||||||
|
|
||||||
| // NodeIterator returns an iterator that returns nodes of the trie. Iteration | ||||||
| // starts at the key after the given start key. And error will be returned | ||||||
| // if fails to create node iterator. | ||||||
|
|
@@ -277,6 +281,11 @@ func (db *CachingDB) TrieDB() *triedb.Database { | |||||
| return db.triedb | ||||||
| } | ||||||
|
|
||||||
| // DiskDB returns the underlying disk database for direct access. | ||||||
| func (db *CachingDB) DiskDB() ethdb.KeyValueStore { | ||||||
| return db.disk | ||||||
| } | ||||||
|
|
||||||
| // PointCache returns the cache of evaluated curve points. | ||||||
| func (db *CachingDB) PointCache() *utils.PointCache { | ||||||
| return db.pointCache | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally, add every access depth and let the consumer do its own filtering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're going to want to separate account trie and storage tries