forked from cerc-io/plugeth
Merge pull request #3184 from karalabe/import-gas-use
cmd/geth, code, eth/downloader: tune import logs and mem stats
This commit is contained in:
commit
28cc3cc960
@ -20,7 +20,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
@ -85,37 +87,62 @@ func importChain(ctx *cli.Context) error {
|
|||||||
chain, chainDb := utils.MakeChain(ctx, stack)
|
chain, chainDb := utils.MakeChain(ctx, stack)
|
||||||
defer chainDb.Close()
|
defer chainDb.Close()
|
||||||
|
|
||||||
|
// Start periodically gathering memory profiles
|
||||||
|
var peakMemAlloc, peakMemSys uint64
|
||||||
|
go func() {
|
||||||
|
stats := new(runtime.MemStats)
|
||||||
|
for {
|
||||||
|
runtime.ReadMemStats(stats)
|
||||||
|
if atomic.LoadUint64(&peakMemAlloc) < stats.Alloc {
|
||||||
|
atomic.StoreUint64(&peakMemAlloc, stats.Alloc)
|
||||||
|
}
|
||||||
|
if atomic.LoadUint64(&peakMemSys) < stats.Sys {
|
||||||
|
atomic.StoreUint64(&peakMemSys, stats.Sys)
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Import the chain
|
// Import the chain
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
||||||
utils.Fatalf("Import error: %v", err)
|
utils.Fatalf("Import error: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Import done in %v.\n", time.Since(start))
|
fmt.Printf("Import done in %v.\n\n", time.Since(start))
|
||||||
|
|
||||||
if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
|
// Output pre-compaction stats mostly to see the import trashing
|
||||||
// Output pre-compaction stats mostly to see the import trashing
|
db := chainDb.(*ethdb.LDBDatabase)
|
||||||
stats, err := db.LDB().GetProperty("leveldb.stats")
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Failed to read database stats: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(stats)
|
|
||||||
fmt.Printf("Trie cache misses: %d\n", trie.CacheMisses())
|
|
||||||
fmt.Printf("Trie cache unloads: %d\n\n", trie.CacheUnloads())
|
|
||||||
|
|
||||||
// Compact the entire database to more accurately measure disk io and print the stats
|
stats, err := db.LDB().GetProperty("leveldb.stats")
|
||||||
start = time.Now()
|
if err != nil {
|
||||||
fmt.Println("Compacting entire database...")
|
utils.Fatalf("Failed to read database stats: %v", err)
|
||||||
if err = db.LDB().CompactRange(util.Range{}); err != nil {
|
|
||||||
utils.Fatalf("Compaction failed: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Compaction done in %v.\n", time.Since(start))
|
|
||||||
|
|
||||||
stats, err = db.LDB().GetProperty("leveldb.stats")
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Failed to read database stats: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(stats)
|
|
||||||
}
|
}
|
||||||
|
fmt.Println(stats)
|
||||||
|
fmt.Printf("Trie cache misses: %d\n", trie.CacheMisses())
|
||||||
|
fmt.Printf("Trie cache unloads: %d\n\n", trie.CacheUnloads())
|
||||||
|
|
||||||
|
// Print the memory statistics used by the importing
|
||||||
|
mem := new(runtime.MemStats)
|
||||||
|
runtime.ReadMemStats(mem)
|
||||||
|
|
||||||
|
fmt.Printf("Object memory: %.3f MB current, %.3f MB peak\n", float64(mem.Alloc)/1024/1024, float64(atomic.LoadUint64(&peakMemAlloc))/1024/1024)
|
||||||
|
fmt.Printf("System memory: %.3f MB current, %.3f MB peak\n", float64(mem.Sys)/1024/1024, float64(atomic.LoadUint64(&peakMemSys))/1024/1024)
|
||||||
|
fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000)
|
||||||
|
fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs))
|
||||||
|
|
||||||
|
// Compact the entire database to more accurately measure disk io and print the stats
|
||||||
|
start = time.Now()
|
||||||
|
fmt.Println("Compacting entire database...")
|
||||||
|
if err = db.LDB().CompactRange(util.Range{}); err != nil {
|
||||||
|
utils.Fatalf("Compaction failed: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
|
||||||
|
|
||||||
|
stats, err = db.LDB().GetProperty("leveldb.stats")
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to read database stats: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println(stats)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +774,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
|
|||||||
if stats.ignored > 0 {
|
if stats.ignored > 0 {
|
||||||
ignored = fmt.Sprintf(" (%d ignored)", stats.ignored)
|
ignored = fmt.Sprintf(" (%d ignored)", stats.ignored)
|
||||||
}
|
}
|
||||||
glog.V(logger.Info).Infof("imported %d receipts%s in %9v. #%d [%x… / %x…]", stats.processed, ignored, common.PrettyDuration(time.Since(start)), last.Number(), first.Hash().Bytes()[:4], last.Hash().Bytes()[:4])
|
glog.V(logger.Info).Infof("imported %d receipts in %9v. #%d [%x… / %x…]%s", stats.processed, common.PrettyDuration(time.Since(start)), last.Number(), first.Hash().Bytes()[:4], last.Hash().Bytes()[:4], ignored)
|
||||||
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@ -981,6 +981,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
|||||||
|
|
||||||
stats.processed++
|
stats.processed++
|
||||||
if glog.V(logger.Info) {
|
if glog.V(logger.Info) {
|
||||||
|
stats.usedGas += usedGas.Uint64()
|
||||||
stats.report(chain, i)
|
stats.report(chain, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -993,6 +994,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
|||||||
// insertStats tracks and reports on block insertion.
|
// insertStats tracks and reports on block insertion.
|
||||||
type insertStats struct {
|
type insertStats struct {
|
||||||
queued, processed, ignored int
|
queued, processed, ignored int
|
||||||
|
usedGas uint64
|
||||||
lastIndex int
|
lastIndex int
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
}
|
}
|
||||||
@ -1004,10 +1006,15 @@ const statsReportLimit = 8 * time.Second
|
|||||||
// report prints statistics if some number of blocks have been processed
|
// report prints statistics if some number of blocks have been processed
|
||||||
// or more than a few seconds have passed since the last message.
|
// or more than a few seconds have passed since the last message.
|
||||||
func (st *insertStats) report(chain []*types.Block, index int) {
|
func (st *insertStats) report(chain []*types.Block, index int) {
|
||||||
|
// Fetch the timings for the batch
|
||||||
var (
|
var (
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
elapsed = now.Sub(st.startTime)
|
elapsed = now.Sub(st.startTime)
|
||||||
)
|
)
|
||||||
|
if elapsed == 0 { // Yes Windows, I'm looking at you
|
||||||
|
elapsed = 1
|
||||||
|
}
|
||||||
|
// If we're at the last block of the batch or report period reached, log
|
||||||
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
||||||
start, end := chain[st.lastIndex], chain[index]
|
start, end := chain[st.lastIndex], chain[index]
|
||||||
txcount := countTransactions(chain[st.lastIndex : index+1])
|
txcount := countTransactions(chain[st.lastIndex : index+1])
|
||||||
@ -1016,7 +1023,13 @@ func (st *insertStats) report(chain []*types.Block, index int) {
|
|||||||
if st.queued > 0 || st.ignored > 0 {
|
if st.queued > 0 || st.ignored > 0 {
|
||||||
extra = fmt.Sprintf(" (%d queued %d ignored)", st.queued, st.ignored)
|
extra = fmt.Sprintf(" (%d queued %d ignored)", st.queued, st.ignored)
|
||||||
}
|
}
|
||||||
glog.Infof("imported %d blocks%s, %5d txs in %9v. #%v [%x… / %x…]\n", st.processed, extra, txcount, common.PrettyDuration(elapsed), end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
|
hashes := ""
|
||||||
|
if st.processed > 1 {
|
||||||
|
hashes = fmt.Sprintf("%x… / %x…", start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
|
||||||
|
} else {
|
||||||
|
hashes = fmt.Sprintf("%x…", end.Hash().Bytes()[:4])
|
||||||
|
}
|
||||||
|
glog.Infof("imported %d blocks, %5d txs (%7.3f Mg) in %9v (%6.3f Mg/s). #%v [%s]%s", st.processed, txcount, float64(st.usedGas)/1000000, common.PrettyDuration(elapsed), float64(st.usedGas)*1000/float64(elapsed), end.Number(), hashes, extra)
|
||||||
|
|
||||||
*st = insertStats{startTime: now, lastIndex: index}
|
*st = insertStats{startTime: now, lastIndex: index}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +436,7 @@ func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, rec
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
||||||
return nil, nil, nil, nil
|
return nil, nil, new(big.Int), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
|
func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
|
||||||
|
@ -952,7 +952,7 @@ func (d *Downloader) fetchNodeData() error {
|
|||||||
|
|
||||||
// Log a message to the user and return
|
// Log a message to the user and return
|
||||||
if delivered > 0 {
|
if delivered > 0 {
|
||||||
glog.V(logger.Info).Infof("imported %d state entries in %9v: processed %d, pending at least %d", delivered, common.PrettyDuration(time.Since(start)), d.syncStatsStateDone, pending)
|
glog.V(logger.Info).Infof("imported %3d state entries in %9v: processed %d, pending at least %d", delivered, common.PrettyDuration(time.Since(start)), d.syncStatsStateDone, pending)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user