|
|
@@ -20,7 +20,9 @@ import (
|
|
|
"fmt"
|
|
|
"os"
|
|
|
"path/filepath"
|
|
|
+ "runtime"
|
|
|
"strconv"
|
|
|
+ "sync/atomic"
|
|
|
"time"
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
|
@@ -85,37 +87,62 @@ func importChain(ctx *cli.Context) error {
|
|
|
chain, chainDb := utils.MakeChain(ctx, stack)
|
|
|
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
|
|
|
start := time.Now()
|
|
|
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
|
|
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
|
|
|
- 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())
|
|
|
+ // Output pre-compaction stats mostly to see the import trashing
|
|
|
+ db := chainDb.(*ethdb.LDBDatabase)
|
|
|
|
|
|
- // 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", 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.Printf("Trie cache misses: %d\n", trie.CacheMisses())
|
|
|
+ fmt.Printf("Trie cache unloads: %d\n\n", trie.CacheUnloads())
|
|
|
|
|
|
- stats, err = db.LDB().GetProperty("leveldb.stats")
|
|
|
- if err != nil {
|
|
|
- utils.Fatalf("Failed to read database stats: %v", err)
|
|
|
- }
|
|
|
- fmt.Println(stats)
|
|
|
+ // 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
|
|
|
}
|
|
|
|