mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
more changes (wip)
This commit is contained in:
parent
b01202e3fe
commit
90175152bb
7 changed files with 51 additions and 165 deletions
|
|
@ -655,13 +655,6 @@ func (bc *BlockChain) processBlockWithAccessList(parentRoot common.Hash, block *
|
|||
// AccountLoaded/StorageLoaded come from the BAL access list (deduplicated);
|
||||
// per-StateDB sums would over-count addresses touched by multiple phases.
|
||||
stats.StateCounts = res.Counts
|
||||
stats.StateCounts.Add(stateTransition.WriteCounts())
|
||||
if al := block.AccessList(); al != nil {
|
||||
stats.StateCounts.AccountLoaded = al.UniqueAccountCount()
|
||||
stats.StateCounts.StorageLoaded = al.UniqueStorageSlotCount()
|
||||
}
|
||||
stats.StateCounts.CodeLoaded = res.CodeLoaded
|
||||
stats.StateCounts.CodeLoadBytes = res.CodeLoadBytes
|
||||
|
||||
stats.Execution = res.ExecTime
|
||||
stats.ExecWall = res.ExecTime
|
||||
|
|
@ -674,19 +667,13 @@ func (bc *BlockChain) processBlockWithAccessList(parentRoot common.Hash, block *
|
|||
stats.DatabaseCommit = m.TrieDBCommits
|
||||
stats.Prefetch = m.StatePrefetch
|
||||
}
|
||||
// Sum-of-CPU-time across per-tx, BAL state-transition, and prefetcher paths.
|
||||
var prefetchAccountReads, prefetchStorageReads time.Duration
|
||||
if pr, ok := prefetchReader.(interface {
|
||||
PrefetchReadTimes() (time.Duration, time.Duration)
|
||||
}); ok {
|
||||
prefetchAccountReads, prefetchStorageReads = pr.PrefetchReadTimes()
|
||||
}
|
||||
prefetchAccountReads, prefetchStorageReads = prefetchReader.(*.PrefetchReadTimes()
|
||||
|
||||
balAccountReads, balStorageReads := stateTransition.ReadTimes()
|
||||
stats.AccountReads = res.Reads.Account + prefetchAccountReads + balAccountReads
|
||||
stats.StorageReads = res.Reads.Storage + prefetchStorageReads + balStorageReads
|
||||
stats.CodeReads = res.Reads.Code
|
||||
stats.Prefetch = prefetchReader.(state.PrefetcherMetricer).Metrics().Elapsed
|
||||
/*
|
||||
stats.AccountReads = res.Reads.Account + prefetchAccountReads + balAccountReads
|
||||
stats.StorageReads = res.Reads.Storage + prefetchStorageReads + balStorageReads
|
||||
stats.CodeReads = res.Reads.Code
|
||||
*/
|
||||
|
||||
if r, ok := prefetchReader.(state.ReaderStater); ok {
|
||||
stats.StateReadCacheStats = r.GetStats()
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ type ExecuteStats struct {
|
|||
StorageCommits time.Duration // Time spent on the storage trie commit
|
||||
CodeReads time.Duration // Time spent on the contract code read
|
||||
|
||||
// State-mutation counts. StorageUpdated/StorageDeleted are int64
|
||||
// (snapshot from atomic.Int64 on StateDB).
|
||||
state.StateCounts
|
||||
// TODO: where is code bytes loaded metric?
|
||||
|
||||
Execution time.Duration // Time spent on the EVM execution
|
||||
Validation time.Duration // Time spent on the block validation
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package state
|
|||
import (
|
||||
"maps"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -41,17 +40,6 @@ type BALStateTransition struct {
|
|||
tries sync.Map //map[common.Address]Trie
|
||||
deletions map[common.Address]struct{}
|
||||
|
||||
// Storage/read counters are atomic — written from per-address goroutines.
|
||||
// account/code counters are plain int — written single-threaded.
|
||||
accountDeleted int
|
||||
accountUpdated int
|
||||
storageDeleted atomic.Int64
|
||||
storageUpdated atomic.Int64
|
||||
codeUpdated int
|
||||
codeUpdateBytes int
|
||||
accountReadNS atomic.Int64
|
||||
storageReadNS atomic.Int64
|
||||
|
||||
stateUpdate *stateUpdate
|
||||
|
||||
metrics BALStateTransitionMetrics
|
||||
|
|
@ -64,23 +52,6 @@ func (s *BALStateTransition) Metrics() *BALStateTransitionMetrics {
|
|||
return &s.metrics
|
||||
}
|
||||
|
||||
// ReadTimes returns the accumulated state-read times.
|
||||
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 from the parallel state-root pass.
|
||||
func (s *BALStateTransition) WriteCounts() StateCounts {
|
||||
return StateCounts{
|
||||
AccountUpdated: s.accountUpdated,
|
||||
AccountDeleted: s.accountDeleted,
|
||||
StorageUpdated: s.storageUpdated.Load(),
|
||||
StorageDeleted: s.storageDeleted.Load(),
|
||||
CodeUpdated: s.codeUpdated,
|
||||
CodeUpdateBytes: s.codeUpdateBytes,
|
||||
}
|
||||
}
|
||||
|
||||
type BALStateTransitionMetrics struct {
|
||||
// trie hashing metrics
|
||||
AccountUpdate time.Duration
|
||||
|
|
@ -223,9 +194,7 @@ func (s *BALStateTransition) commitAccount(addr common.Address) (*accountUpdate,
|
|||
for key, value := range s.diffs[addr].StorageWrites {
|
||||
hash := crypto.Keccak256Hash(key[:])
|
||||
op.storages[hash] = encode(value)
|
||||
storageReadStart := time.Now()
|
||||
storage, err := s.reader.Storage(addr, key)
|
||||
s.storageReadNS.Add(time.Since(storageReadStart).Nanoseconds())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -365,10 +334,13 @@ func (s *BALStateTransition) CommitWithUpdate(block uint64, deleteEmptyObjects b
|
|||
return common.Hash{}, nil, err
|
||||
}
|
||||
|
||||
accountUpdatedMeter.Mark(int64(s.accountUpdated))
|
||||
storageUpdatedMeter.Mark(s.storageUpdated.Load())
|
||||
accountDeletedMeter.Mark(int64(s.accountDeleted))
|
||||
storageDeletedMeter.Mark(s.storageDeleted.Load())
|
||||
/*
|
||||
TODO: derive these from the BAL
|
||||
accountUpdatedMeter.Mark(int64(s.accountUpdated))
|
||||
storageUpdatedMeter.Mark(s.storageUpdated.Load())
|
||||
accountDeletedMeter.Mark(int64(s.accountDeleted))
|
||||
storageDeletedMeter.Mark(s.storageDeleted.Load())
|
||||
*/
|
||||
accountTrieUpdatedMeter.Mark(int64(accountTrieNodesUpdated))
|
||||
accountTrieDeletedMeter.Mark(int64(accountTrieNodesDeleted))
|
||||
storageTriesUpdatedMeter.Mark(int64(storageTrieNodesUpdated))
|
||||
|
|
@ -421,9 +393,7 @@ func (s *BALStateTransition) IntermediateRoot(_ bool) common.Hash {
|
|||
defer wg.Done()
|
||||
|
||||
// 1 (c): update each mutated account, producing the post-block state object by applying the state mutations to the prestate (retrieved in 1a).
|
||||
accountReadStart := time.Now()
|
||||
acct, err := s.reader.Account(address)
|
||||
s.accountReadNS.Add(time.Since(accountReadStart).Nanoseconds())
|
||||
if err != nil {
|
||||
s.setError(err)
|
||||
return
|
||||
|
|
@ -450,12 +420,8 @@ func (s *BALStateTransition) IntermediateRoot(_ bool) common.Hash {
|
|||
if val != (common.Hash{}) {
|
||||
updateKeys = append(updateKeys, key[:])
|
||||
updateValues = append(updateValues, common.TrimLeftZeroes(val[:]))
|
||||
|
||||
s.storageUpdated.Add(1)
|
||||
} else {
|
||||
deleteKeys = append(deleteKeys, key[:])
|
||||
|
||||
s.storageDeleted.Add(1)
|
||||
}
|
||||
}
|
||||
if err := tr.UpdateStorageBatch(address, updateKeys, updateValues); err != nil {
|
||||
|
|
@ -509,7 +475,6 @@ func (s *BALStateTransition) IntermediateRoot(_ bool) common.Hash {
|
|||
return common.Hash{}
|
||||
}
|
||||
s.deletions[mutatedAddr] = struct{}{}
|
||||
s.accountDeleted++
|
||||
} else {
|
||||
acct, code := s.updateAccount(mutatedAddr)
|
||||
|
||||
|
|
@ -520,15 +485,12 @@ func (s *BALStateTransition) IntermediateRoot(_ bool) common.Hash {
|
|||
s.setError(err)
|
||||
return common.Hash{}
|
||||
}
|
||||
s.codeUpdated++
|
||||
s.codeUpdateBytes += len(code)
|
||||
}
|
||||
if err := s.stateTrie.UpdateAccount(mutatedAddr, acct, len(code)); err != nil {
|
||||
s.setError(err)
|
||||
return common.Hash{}
|
||||
}
|
||||
s.postStates[mutatedAddr] = acct
|
||||
s.accountUpdated++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ package state
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/overlay"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
|
|
@ -241,26 +239,6 @@ func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (Reader, Reade
|
|||
return ra, rb, nil
|
||||
}
|
||||
|
||||
type ReaderEIP7928Metrics struct {
|
||||
// the total amount of time it took to complete the scheduled workload
|
||||
WallElapsed time.Duration
|
||||
// the aggregated total time spent on state loading by all workers
|
||||
TotalElapsed time.Duration
|
||||
// the amount of accounts loaded
|
||||
Accounts int
|
||||
// the amount of storage slots loaded
|
||||
Storages int
|
||||
// number of accounts with code loaded
|
||||
Codes int
|
||||
// total amount of code bytes loaded
|
||||
CodeBytes int
|
||||
}
|
||||
|
||||
type ReaderEIP7928 interface {
|
||||
Reader
|
||||
Metrics() *ReaderEIP7928Metrics
|
||||
}
|
||||
|
||||
// ReaderEIP7928 creates a state reader with the manner of Block-level accessList.
|
||||
func (db *CachingDB) ReaderEIP7928(stateRoot common.Hash, accessList map[common.Address][]common.Hash, threads int) (Reader, error) {
|
||||
base, err := db.StateReader(stateRoot)
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ package state
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/overlay"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
|
@ -32,6 +28,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie/transitiontrie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// ContractCodeReader defines the interface for accessing contract code.
|
||||
|
|
@ -564,13 +562,3 @@ func (r *reader) GetStats() ReaderStats {
|
|||
StateStats: r.GetStateStats(),
|
||||
}
|
||||
}
|
||||
|
||||
// PrefetchReadTimes forwards to the wrapped prefetcher, or returns zero.
|
||||
func (r *reader) PrefetchReadTimes() (account, storage time.Duration) {
|
||||
if pr, ok := r.StateReader.(interface {
|
||||
PrefetchReadTimes() (time.Duration, time.Duration)
|
||||
}); ok {
|
||||
return pr.PrefetchReadTimes()
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ package state
|
|||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
|
@ -88,10 +87,33 @@ type prefetchStateReader struct {
|
|||
done chan struct{}
|
||||
term chan struct{}
|
||||
closeOnce sync.Once
|
||||
start time.Time
|
||||
metrics PrefetchMetrics
|
||||
}
|
||||
|
||||
// Atomic — process() runs across N goroutines.
|
||||
accountReadNS atomic.Int64
|
||||
storageReadNS atomic.Int64
|
||||
type PrefetchMetrics struct {
|
||||
// the total amount of time it took to complete the scheduled workload
|
||||
Elapsed time.Duration
|
||||
// the aggregated total time spent on state loading by all workers
|
||||
// TODO (jwasinger): add back in after i finish initial commit(s) with only the changes I think will be ultimately merged
|
||||
// TotalElapsed time.Duration
|
||||
|
||||
/*
|
||||
// TODO: source these from the other reader where they are implemented
|
||||
// the amount of accounts loaded
|
||||
Accounts int
|
||||
// the amount of storage slots loaded
|
||||
Storages int
|
||||
// number of accounts with code loaded
|
||||
Codes int
|
||||
// total amount of code bytes loaded
|
||||
CodeBytes int
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
type PrefetcherMetricer interface {
|
||||
Metrics() PrefetchMetrics
|
||||
}
|
||||
|
||||
func newPrefetchStateReader(reader StateReader, accessList bal.StorageKeys, nThreads int) *prefetchStateReader {
|
||||
|
|
@ -186,13 +208,9 @@ func (r *prefetchStateReader) process(start, limit int) {
|
|||
return
|
||||
default:
|
||||
if j == 0 {
|
||||
accountReadStart := time.Now()
|
||||
r.StateReader.Account(t.addr)
|
||||
r.accountReadNS.Add(time.Since(accountReadStart).Nanoseconds())
|
||||
} else {
|
||||
storageReadStart := time.Now()
|
||||
r.StateReader.Storage(t.addr, t.slots[j-1])
|
||||
r.storageReadNS.Add(time.Since(storageReadStart).Nanoseconds())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,6 +391,9 @@ func (r *readerTracker) TouchStorage(addr common.Address, slot common.Hash) {
|
|||
list[slot] = struct{}{}
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: ensure these are accounted for
|
||||
|
||||
// GetStateStats forwards stats from the wrapped reader; without this, BAL
|
||||
// blocks would emit zero cache hit/miss counts.
|
||||
func (r *prefetchStateReader) GetStateStats() StateReaderStats {
|
||||
|
|
@ -387,3 +408,4 @@ func (r *prefetchStateReader) GetStateStats() StateReaderStats {
|
|||
func (r *prefetchStateReader) PrefetchReadTimes() (account, storage time.Duration) {
|
||||
return time.Duration(r.accountReadNS.Load()), time.Duration(r.storageReadNS.Load())
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -223,6 +223,10 @@ func (s *StateDB) WithReader(reader Reader) *StateDB {
|
|||
return cpy
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// TODO (jwasinger): add these back in a subsequent commit
|
||||
|
||||
// ReadDurations groups the {Account, Storage, Code} state-read times.
|
||||
// Sum-of-CPU-time when aggregated across BAL phase statedbs.
|
||||
type ReadDurations struct {
|
||||
|
|
@ -237,60 +241,7 @@ func (r *ReadDurations) Add(other ReadDurations) {
|
|||
r.Storage += other.Storage
|
||||
r.Code += other.Code
|
||||
}
|
||||
|
||||
// StateCounts is a plain-int snapshot of state-mutation counters. Atomic
|
||||
// fields on StateDB are Load()'d at the SnapshotCounts boundary.
|
||||
type StateCounts struct {
|
||||
AccountLoaded int // accounts retrieved from the database during the state transition
|
||||
AccountUpdated int // accounts updated during the state transition
|
||||
AccountDeleted int // accounts deleted during the state transition
|
||||
StorageLoaded int // storage slots retrieved from the database during the state transition
|
||||
StorageUpdated int64 // storage slots updated (snapshotted from atomic on StateDB)
|
||||
StorageDeleted int64 // storage slots deleted (snapshotted from atomic on StateDB)
|
||||
CodeLoaded int // contract code reads
|
||||
CodeLoadBytes int // total bytes of resolved code
|
||||
CodeUpdated int // code writes (CREATE/CREATE2/EIP-7702)
|
||||
CodeUpdateBytes int // total bytes of persisted code written
|
||||
}
|
||||
|
||||
// Add merges other into c.
|
||||
func (c *StateCounts) Add(other StateCounts) {
|
||||
c.AccountLoaded += other.AccountLoaded
|
||||
c.AccountUpdated += other.AccountUpdated
|
||||
c.AccountDeleted += other.AccountDeleted
|
||||
c.StorageLoaded += other.StorageLoaded
|
||||
c.StorageUpdated += other.StorageUpdated
|
||||
c.StorageDeleted += other.StorageDeleted
|
||||
c.CodeLoaded += other.CodeLoaded
|
||||
c.CodeLoadBytes += other.CodeLoadBytes
|
||||
c.CodeUpdated += other.CodeUpdated
|
||||
c.CodeUpdateBytes += other.CodeUpdateBytes
|
||||
}
|
||||
|
||||
// SnapshotCounts returns a plain-int copy of the state-mutation counters.
|
||||
func (s *StateDB) SnapshotCounts() StateCounts {
|
||||
return StateCounts{
|
||||
AccountLoaded: s.AccountLoaded,
|
||||
AccountUpdated: s.AccountUpdated,
|
||||
AccountDeleted: s.AccountDeleted,
|
||||
StorageLoaded: s.StorageLoaded,
|
||||
StorageUpdated: s.StorageUpdated.Load(),
|
||||
StorageDeleted: s.StorageDeleted.Load(),
|
||||
CodeLoaded: s.CodeLoaded,
|
||||
CodeLoadBytes: s.CodeLoadBytes,
|
||||
CodeUpdated: s.CodeUpdated,
|
||||
CodeUpdateBytes: s.CodeUpdateBytes,
|
||||
}
|
||||
}
|
||||
|
||||
// SnapshotReads returns the {Account, Storage, Code} read durations.
|
||||
func (s *StateDB) SnapshotReads() ReadDurations {
|
||||
return ReadDurations{
|
||||
Account: s.AccountReads,
|
||||
Storage: s.StorageReads,
|
||||
Code: s.CodeReads,
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// SnapshotCodeLoads returns addresses whose code body was fetched, mapped to
|
||||
// byte length. Used to deduplicate code-load events across BAL phase StateDBs.
|
||||
|
|
|
|||
Loading…
Reference in a new issue