Skip to content

Commit

Permalink
core: split out detailed trie access metrics from insertion time
Browse files Browse the repository at this point in the history
  • Loading branch information
karalabe committed Mar 22, 2019
1 parent 09924cb commit 32524ef
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 17 deletions.
29 changes: 27 additions & 2 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ import (
)

var (
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
accountCommitTimer = metrics.NewRegisteredTimer("chain/account/commits", nil)

storageReadTimer = metrics.NewRegisteredTimer("chain/storage/reads", nil)
storageHashTimer = metrics.NewRegisteredTimer("chain/storage/hashes", nil)
storageUpdateTimer = metrics.NewRegisteredTimer("chain/storage/updates", nil)
storageCommitTimer = metrics.NewRegisteredTimer("chain/storage/commits", nil)

blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil)
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
Expand Down Expand Up @@ -1249,10 +1259,26 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
if err != nil {
return it.index, events, coalescedLogs, err
}

// Update the metrics subsystem with all the measurements
accountReadTimer.Update(state.AccountReads)
accountHashTimer.Update(state.AccountHashes)
accountUpdateTimer.Update(state.AccountUpdates)
accountCommitTimer.Update(state.AccountCommits)

storageReadTimer.Update(state.StorageReads)
storageHashTimer.Update(state.StorageHashes)
storageUpdateTimer.Update(state.StorageUpdates)
storageCommitTimer.Update(state.StorageCommits)

trieAccess := state.AccountReads + state.AccountHashes + state.AccountUpdates + state.AccountCommits
trieAccess += state.StorageReads + state.StorageHashes + state.StorageUpdates + state.StorageCommits

blockInsertTimer.UpdateSince(start)
blockExecutionTimer.Update(t1.Sub(t0))
blockExecutionTimer.Update(t1.Sub(t0) - trieAccess)
blockValidationTimer.Update(t2.Sub(t1))
blockWriteTimer.Update(t3.Sub(t2))

switch status {
case CanonStatTy:
log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(),
Expand All @@ -1274,7 +1300,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
"root", block.Root())
events = append(events, ChainSideEvent{block})
}
blockInsertTimer.UpdateSince(start)
stats.processed++
stats.usedGas += usedGas

Expand Down
13 changes: 13 additions & 0 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"io"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
Expand Down Expand Up @@ -177,6 +178,9 @@ func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.
if cached {
return value
}
// Track the amount of time wasted on reading the storge trie
defer func(start time.Time) { self.db.StorageReads += time.Since(start) }(time.Now())

// Otherwise load the value from the database
enc, err := self.getTrie(db).TryGet(key[:])
if err != nil {
Expand Down Expand Up @@ -216,6 +220,9 @@ func (self *stateObject) setState(key, value common.Hash) {

// updateTrie writes cached storage modifications into the object's storage trie.
func (self *stateObject) updateTrie(db Database) Trie {
// Track the amount of time wasted on updating the storge trie
defer func(start time.Time) { self.db.StorageUpdates += time.Since(start) }(time.Now())

tr := self.getTrie(db)
for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
Expand All @@ -240,6 +247,9 @@ func (self *stateObject) updateTrie(db Database) Trie {
// UpdateRoot sets the trie root to the current root hash of
func (self *stateObject) updateRoot(db Database) {
self.updateTrie(db)

// Track the amount of time wasted on hashing the storge trie
defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now())
self.data.Root = self.trie.Hash()
}

Expand All @@ -250,6 +260,9 @@ func (self *stateObject) CommitTrie(db Database) error {
if self.dbErr != nil {
return self.dbErr
}
// Track the amount of time wasted on committing the storge trie
defer func(start time.Time) { self.db.StorageCommits += time.Since(start) }(time.Now())

root, err := self.trie.Commit(nil)
if err == nil {
self.data.Root = root
Expand Down
58 changes: 43 additions & 15 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"math/big"
"sort"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -86,6 +87,16 @@ type StateDB struct {
journal *journal
validRevisions []revision
nextRevisionId int

// Measurements gathered during execution for debugging purposes
AccountReads time.Duration
AccountHashes time.Duration
AccountUpdates time.Duration
AccountCommits time.Duration
StorageReads time.Duration
StorageHashes time.Duration
StorageUpdates time.Duration
StorageCommits time.Duration
}

// Create a new state from a given trie.
Expand Down Expand Up @@ -386,46 +397,58 @@ func (self *StateDB) Suicide(addr common.Address) bool {
//

// updateStateObject writes the given object to the trie.
func (self *StateDB) updateStateObject(stateObject *stateObject) {
func (s *StateDB) updateStateObject(stateObject *stateObject) {
// Track the amount of time wasted on updating the account from the trie
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())

// Encode the account and update the account trie
addr := stateObject.Address()

data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
self.setError(self.trie.TryUpdate(addr[:], data))
s.setError(s.trie.TryUpdate(addr[:], data))
}

// deleteStateObject removes the given object from the state trie.
func (self *StateDB) deleteStateObject(stateObject *stateObject) {
func (s *StateDB) deleteStateObject(stateObject *stateObject) {
// Track the amount of time wasted on deleting the account from the trie
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())

// Delete the account from the trie
stateObject.deleted = true

addr := stateObject.Address()
self.setError(self.trie.TryDelete(addr[:]))
s.setError(s.trie.TryDelete(addr[:]))
}

// Retrieve a state object given by the address. Returns nil if not found.
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects.
if obj := self.stateObjects[addr]; obj != nil {
func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer live objects
if obj := s.stateObjects[addr]; obj != nil {
if obj.deleted {
return nil
}
return obj
}
// Track the amount of time wasted on loading the object from the database
defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now())

// Load the object from the database.
enc, err := self.trie.TryGet(addr[:])
// Load the object from the database
enc, err := s.trie.TryGet(addr[:])
if len(enc) == 0 {
self.setError(err)
s.setError(err)
return nil
}
var data Account
if err := rlp.DecodeBytes(enc, &data); err != nil {
log.Error("Failed to decode state object", "addr", addr, "err", err)
return nil
}
// Insert into the live set.
obj := newObject(self, addr, data)
self.setStateObject(obj)
// Insert into the live set
obj := newObject(s, addr, data)
s.setStateObject(obj)
return obj
}

Expand Down Expand Up @@ -600,6 +623,9 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
s.Finalise(deleteEmptyObjects)

// Track the amount of time wasted on hashing the account trie
defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now())
return s.trie.Hash()
}

Expand All @@ -624,7 +650,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
for addr := range s.journal.dirties {
s.stateObjectsDirty[addr] = struct{}{}
}
// Commit objects to the trie.
// Commit objects to the trie, measuring the elapsed time
for addr, stateObject := range s.stateObjects {
_, isDirty := s.stateObjectsDirty[addr]
switch {
Expand All @@ -647,7 +673,9 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
}
delete(s.stateObjectsDirty, addr)
}
// Write trie changes.
// Write the account trie changes, measuing the amount of wasted time
defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now())

root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
var account Account
if err := rlp.DecodeBytes(leaf, &account); err != nil {
Expand Down

0 comments on commit 32524ef

Please sign in to comment.