mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
trie: count preimages in memuse, commit in KB batches
This commit is contained in:
parent
7dc1f1857e
commit
615145e084
3 changed files with 43 additions and 21 deletions
|
|
@ -20,18 +20,29 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StorageSize is a wrapper around a float value that supports user friendly
|
||||||
|
// formatting.
|
||||||
type StorageSize float64
|
type StorageSize float64
|
||||||
|
|
||||||
func (self StorageSize) String() string {
|
// String implements the stringer interface.
|
||||||
if self > 1000000 {
|
func (s StorageSize) String() string {
|
||||||
return fmt.Sprintf("%.2f mB", self/1000000)
|
if s > 1000000 {
|
||||||
} else if self > 1000 {
|
return fmt.Sprintf("%.2f mB", s/1000000)
|
||||||
return fmt.Sprintf("%.2f kB", self/1000)
|
} else if s > 1000 {
|
||||||
|
return fmt.Sprintf("%.2f kB", s/1000)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%.2f B", self)
|
return fmt.Sprintf("%.2f B", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self StorageSize) Int64() int64 {
|
// TerminalString implements log.TerminalStringer, formatting a string for console
|
||||||
return int64(self)
|
// output during logging.
|
||||||
|
func (s StorageSize) TerminalString() string {
|
||||||
|
if s > 1000000 {
|
||||||
|
return fmt.Sprintf("%.2fmB", s/1000000)
|
||||||
|
} else if s > 1000 {
|
||||||
|
return fmt.Sprintf("%.2fkB", s/1000)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%.2fB", s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -808,7 +808,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
|
||||||
"difficulty": (*hexutil.Big)(head.Difficulty),
|
"difficulty": (*hexutil.Big)(head.Difficulty),
|
||||||
"totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())),
|
"totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())),
|
||||||
"extraData": hexutil.Bytes(head.Extra),
|
"extraData": hexutil.Bytes(head.Extra),
|
||||||
"size": hexutil.Uint64(uint64(b.Size().Int64())),
|
"size": hexutil.Uint64(b.Size()),
|
||||||
"gasLimit": hexutil.Uint64(head.GasLimit),
|
"gasLimit": hexutil.Uint64(head.GasLimit),
|
||||||
"gasUsed": hexutil.Uint64(head.GasUsed),
|
"gasUsed": hexutil.Uint64(head.GasUsed),
|
||||||
"timestamp": (*hexutil.Big)(head.Time),
|
"timestamp": (*hexutil.Big)(head.Time),
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,9 @@ type Database struct {
|
||||||
gcnodes uint64 // Nodes garbage collected since last commit
|
gcnodes uint64 // Nodes garbage collected since last commit
|
||||||
gcsize common.StorageSize // Data storage garbage collected since last commit
|
gcsize common.StorageSize // Data storage garbage collected since last commit
|
||||||
|
|
||||||
size common.StorageSize // Storage size of the memory cache
|
nodesSize common.StorageSize // Storage size of the nodes cache
|
||||||
|
preimagesSize common.StorageSize // Storage size of the preimages cache
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +103,7 @@ func (db *Database) insert(hash common.Hash, blob []byte) {
|
||||||
blob: common.CopyBytes(blob),
|
blob: common.CopyBytes(blob),
|
||||||
children: make(map[common.Hash]int),
|
children: make(map[common.Hash]int),
|
||||||
}
|
}
|
||||||
db.size += common.StorageSize(common.HashLength + len(blob))
|
db.nodesSize += common.StorageSize(common.HashLength + len(blob))
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertPreimage writes a new trie node pre-image to the memory database if it's
|
// insertPreimage writes a new trie node pre-image to the memory database if it's
|
||||||
|
|
@ -113,6 +115,7 @@ func (db *Database) insertPreimage(hash common.Hash, preimage []byte) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
db.preimages[hash] = common.CopyBytes(preimage)
|
db.preimages[hash] = common.CopyBytes(preimage)
|
||||||
|
db.preimagesSize += common.StorageSize(common.HashLength + len(preimage))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node retrieves a cached trie node from memory. If it cannot be found cached,
|
// Node retrieves a cached trie node from memory. If it cannot be found cached,
|
||||||
|
|
@ -198,15 +201,15 @@ func (db *Database) Dereference(child common.Hash, parent common.Hash) {
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
nodes, storage, start := len(db.nodes), db.size, time.Now()
|
nodes, storage, start := len(db.nodes), db.nodesSize, time.Now()
|
||||||
db.dereference(child, parent)
|
db.dereference(child, parent)
|
||||||
|
|
||||||
db.gcnodes += uint64(nodes - len(db.nodes))
|
db.gcnodes += uint64(nodes - len(db.nodes))
|
||||||
db.gcsize += storage - db.size
|
db.gcsize += storage - db.nodesSize
|
||||||
db.gctime += time.Since(start)
|
db.gctime += time.Since(start)
|
||||||
|
|
||||||
log.Debug("Dereferenced trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.size, "time", time.Since(start),
|
log.Debug("Dereferenced trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.nodesSize, "time", time.Since(start),
|
||||||
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.size)
|
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.nodesSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dereference is the private locked version of Dereference.
|
// dereference is the private locked version of Dereference.
|
||||||
|
|
@ -230,7 +233,7 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
|
||||||
db.dereference(hash, child)
|
db.dereference(hash, child)
|
||||||
}
|
}
|
||||||
delete(db.nodes, child)
|
delete(db.nodes, child)
|
||||||
db.size -= common.StorageSize(common.HashLength + len(node.blob))
|
db.nodesSize -= common.StorageSize(common.HashLength + len(node.blob))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,9 +258,15 @@ func (db *Database) Commit(node common.Hash) error {
|
||||||
db.lock.RUnlock()
|
db.lock.RUnlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if batch.ValueSize() > ethdb.IdealBatchSize {
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
batch = db.diskdb.NewBatch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Move the trie itself into the batch, flushing if enough data is accumulated
|
// Move the trie itself into the batch, flushing if enough data is accumulated
|
||||||
nodes, storage := len(db.nodes), db.size
|
nodes, storage := len(db.nodes), db.nodesSize+db.preimagesSize
|
||||||
if err := db.commit(node, &batch); err != nil {
|
if err := db.commit(node, &batch); err != nil {
|
||||||
log.Error("Failed to commit trie from trie database", "err", err)
|
log.Error("Failed to commit trie from trie database", "err", err)
|
||||||
db.lock.RUnlock()
|
db.lock.RUnlock()
|
||||||
|
|
@ -276,10 +285,12 @@ func (db *Database) Commit(node common.Hash) error {
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
db.preimages = make(map[common.Hash][]byte)
|
db.preimages = make(map[common.Hash][]byte)
|
||||||
|
db.preimagesSize = 0
|
||||||
|
|
||||||
db.uncache(node)
|
db.uncache(node)
|
||||||
|
|
||||||
log.Info("Persisted trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.size, "time", time.Since(start),
|
log.Info("Persisted trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.nodesSize, "time", time.Since(start),
|
||||||
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.size)
|
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.nodesSize)
|
||||||
|
|
||||||
// Reset the garbage collection statistics
|
// Reset the garbage collection statistics
|
||||||
db.gcnodes, db.gcsize, db.gctime = 0, 0, 0
|
db.gcnodes, db.gcsize, db.gctime = 0, 0, 0
|
||||||
|
|
@ -327,7 +338,7 @@ func (db *Database) uncache(hash common.Hash) {
|
||||||
db.uncache(child)
|
db.uncache(child)
|
||||||
}
|
}
|
||||||
delete(db.nodes, hash)
|
delete(db.nodes, hash)
|
||||||
db.size -= common.StorageSize(common.HashLength + len(node.blob))
|
db.nodesSize -= common.StorageSize(common.HashLength + len(node.blob))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the current storage size of the memory cache in front of the
|
// Size returns the current storage size of the memory cache in front of the
|
||||||
|
|
@ -336,5 +347,5 @@ func (db *Database) Size() common.StorageSize {
|
||||||
db.lock.RLock()
|
db.lock.RLock()
|
||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
return db.size
|
return db.nodesSize + db.preimagesSize
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue