mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-11 09:21:37 +00:00
core: split BAL read-time access from cached metrics struct
Replace the cached AccountReadTime/StorageReadTime fields (which had a
snapshot-staleness bug fixed in 16e98f5d9 by re-calling Metrics()) with
a live ReadTimes() accessor. Metrics() now only returns commit/hash-phase
timings — it no longer touches atomics. blockchain.go reads atomics
directly via stateTransition.ReadTimes(), eliminating the refresh hack.
Also resolves the I1 fragility: Metrics() returning &s.metrics no longer
involves any writes inside the function, so concurrent callers can't race
on the read-time field updates.
This commit is contained in:
parent
eb4d17595f
commit
546d2b457e
2 changed files with 13 additions and 17 deletions
|
|
@ -677,10 +677,6 @@ func (bc *BlockChain) processBlockWithAccessList(parentRoot common.Hash, block *
|
||||||
stats.DatabaseCommit = m.TrieDBCommits
|
stats.DatabaseCommit = m.TrieDBCommits
|
||||||
stats.Prefetch = m.StatePrefetch
|
stats.Prefetch = m.StatePrefetch
|
||||||
}
|
}
|
||||||
// Refresh BAL read-time cache: commitAccount runs storage reads during
|
|
||||||
// writeBlockWithState, after the first Metrics() snapshot.
|
|
||||||
stateTransition.Metrics()
|
|
||||||
|
|
||||||
// Sum read times across per-tx execution, BAL state-transition, and
|
// Sum read times across per-tx execution, BAL state-transition, and
|
||||||
// prefetcher async fetches. Sum-of-CPU-time, not wall-clock.
|
// prefetcher async fetches. Sum-of-CPU-time, not wall-clock.
|
||||||
if w, ok := prefetchReader.(interface{ WaitPrefetch() }); ok {
|
if w, ok := prefetchReader.(interface{ WaitPrefetch() }); ok {
|
||||||
|
|
@ -692,13 +688,10 @@ func (bc *BlockChain) processBlockWithAccessList(parentRoot common.Hash, block *
|
||||||
}); ok {
|
}); ok {
|
||||||
prefetchAccountReads, prefetchStorageReads = pr.PrefetchReadTimes()
|
prefetchAccountReads, prefetchStorageReads = pr.PrefetchReadTimes()
|
||||||
}
|
}
|
||||||
stats.AccountReads = res.PerTxAccountReads + prefetchAccountReads
|
balAccountReads, balStorageReads := stateTransition.ReadTimes()
|
||||||
stats.StorageReads = res.PerTxStorageReads + prefetchStorageReads
|
stats.AccountReads = res.PerTxAccountReads + prefetchAccountReads + balAccountReads
|
||||||
|
stats.StorageReads = res.PerTxStorageReads + prefetchStorageReads + balStorageReads
|
||||||
stats.CodeReads = res.PerTxCodeReads
|
stats.CodeReads = res.PerTxCodeReads
|
||||||
if m := res.StateTransitionMetrics; m != nil {
|
|
||||||
stats.AccountReads += m.AccountReadTime
|
|
||||||
stats.StorageReads += m.StorageReadTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache stats from the shared prefetch reader (accumulates centrally).
|
// Cache stats from the shared prefetch reader (accumulates centrally).
|
||||||
if r, ok := prefetchReader.(state.ReaderStater); ok {
|
if r, ok := prefetchReader.(state.ReaderStater); ok {
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,20 @@ type BALStateTransition struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Metrics returns the cached commit/hash-phase timings. Read-time atomics
|
||||||
|
// are exposed separately via ReadTimes; that decoupling avoids the
|
||||||
|
// snapshot-staleness pitfall when commitAccount runs more reads after
|
||||||
|
// Metrics is first called.
|
||||||
func (s *BALStateTransition) Metrics() *BALStateTransitionMetrics {
|
func (s *BALStateTransition) Metrics() *BALStateTransitionMetrics {
|
||||||
s.metrics.AccountReadTime = time.Duration(s.accountReadNS.Load())
|
|
||||||
s.metrics.StorageReadTime = time.Duration(s.storageReadNS.Load())
|
|
||||||
return &s.metrics
|
return &s.metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadTimes returns the current accumulated read times from atomic counters.
|
||||||
|
// Always live; safe to call at any point after IntermediateRoot/Commit work.
|
||||||
|
func (s *BALStateTransition) ReadTimes() (account, storage time.Duration) {
|
||||||
|
return time.Duration(s.accountReadNS.Load()), time.Duration(s.storageReadNS.Load())
|
||||||
|
}
|
||||||
|
|
||||||
// WriteCounts returns the state-mutation counts tracked during the parallel
|
// WriteCounts returns the state-mutation counts tracked during the parallel
|
||||||
// state-root computation.
|
// state-root computation.
|
||||||
func (s *BALStateTransition) WriteCounts() StateCounts {
|
func (s *BALStateTransition) WriteCounts() StateCounts {
|
||||||
|
|
@ -96,11 +104,6 @@ type BALStateTransitionMetrics struct {
|
||||||
SnapshotCommits time.Duration
|
SnapshotCommits time.Duration
|
||||||
TrieDBCommits time.Duration
|
TrieDBCommits time.Duration
|
||||||
TotalCommitTime time.Duration
|
TotalCommitTime time.Duration
|
||||||
|
|
||||||
// State-root recomputation read times. Sum of CPU time across the per-
|
|
||||||
// address goroutines that call s.reader.Account/Storage during commit.
|
|
||||||
AccountReadTime time.Duration
|
|
||||||
StorageReadTime time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBALStateTransition(block *types.Block, prefetchReader Reader, db Database, parentRoot common.Hash) (*BALStateTransition, error) {
|
func NewBALStateTransition(block *types.Block, prefetchReader Reader, db Database, parentRoot common.Hash) (*BALStateTransition, error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue