diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go index 59dd11fff63adbe8c359514ab7a86bce51aa86f3..f9786b2a849885e9a40687d303e623bc50dc19b5 100644 --- a/cmd/hack/hack.go +++ b/cmd/hack/hack.go @@ -23,6 +23,7 @@ import ( "syscall" "time" + "github.com/AskAlexSharov/lmdb-go/lmdb" "github.com/dustin/go-humanize" "github.com/ledgerwatch/bolt" "github.com/ledgerwatch/turbo-geth/common" @@ -369,46 +370,52 @@ func accountSavings(db *bolt.DB) (int, int) { return emptyRoots, emptyCodes } -func allBuckets(db *bolt.DB) [][]byte { - bucketList := [][]byte{} - err := db.View(func(tx *bolt.Tx) error { - err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { - n := make([]byte, len(name)) - copy(n, name) - bucketList = append(bucketList, n) - return nil - }) - return err - }) - if err != nil { - panic(fmt.Sprintf("Could view db: %s", err)) - } - return bucketList -} - func printBuckets(db *bolt.DB) { - bucketList := allBuckets(db) - for _, bucket := range bucketList { + for _, bucket := range dbutils.Buckets { fmt.Printf("%s\n", bucket) } } func bucketStats(chaindata string) { - db, err := bolt.Open(chaindata, 0600, &bolt.Options{ReadOnly: true}) - check(err) - bucketList := allBuckets(db) - //bucketList := [][]byte{dbutils.IntermediateTrieHashBucket} - fmt.Printf(",BranchPageN,BranchOverflowN,LeafPageN,LeafOverflowN,KeyN,Depth,BranchAlloc,BranchInuse,LeafAlloc,LeafInuse,BucketN,InlineBucketN,InlineBucketInuse\n") - db.View(func(tx *bolt.Tx) error { - for _, bucket := range bucketList { - b := tx.Bucket(bucket) - bs := b.Stats() - fmt.Printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", string(bucket), - bs.BranchPageN, bs.BranchOverflowN, bs.LeafPageN, bs.LeafOverflowN, bs.KeyN, bs.Depth, bs.BranchAlloc, bs.BranchInuse, - bs.LeafAlloc, bs.LeafInuse, bs.BucketN, bs.InlineBucketN, bs.InlineBucketInuse) - } - return nil - }) + t := ethdb.Bolt + bucketList := dbutils.Buckets + + switch t { + case ethdb.Bolt: + db, err := bolt.Open(chaindata, 0600, &bolt.Options{ReadOnly: true}) + check(err) + //bucketList := [][]byte{dbutils.IntermediateTrieHashBucket} + + fmt.Printf(",BranchPageN,BranchOverflowN,LeafPageN,LeafOverflowN,KeyN,Depth,BranchAlloc,BranchInuse,LeafAlloc,LeafInuse,BucketN,InlineBucketN,InlineBucketInuse\n") + _ = db.View(func(tx *bolt.Tx) error { + for _, bucket := range bucketList { + b := tx.Bucket(bucket) + bs := b.Stats() + fmt.Printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", string(bucket), + bs.BranchPageN, bs.BranchOverflowN, bs.LeafPageN, bs.LeafOverflowN, bs.KeyN, bs.Depth, bs.BranchAlloc, bs.BranchInuse, + bs.LeafAlloc, bs.LeafInuse, bs.BucketN, bs.InlineBucketN, bs.InlineBucketInuse) + } + return nil + }) + case ethdb.Lmdb: + env, err := lmdb.NewEnv() + check(err) + err = env.Open(chaindata, lmdb.Readonly, 0664) + check(err) + + fmt.Printf(",BranchPageN,LeafPageN,OverflowN,Entries\n") + _ = env.View(func(tx *lmdb.Txn) error { + for _, bucket := range bucketList { + dbi, bucketErr := tx.OpenDBI(string(bucket), lmdb.Readonly) + check(bucketErr) + bs, statErr := tx.Stat(dbi) + check(statErr) + fmt.Printf("%s,%d,%d,%d,%d\n", string(bucket), + bs.BranchPages, bs.LeafPages, bs.OverflowPages, bs.Entries) + } + return nil + }) + } } func readTrieLog() ([]float64, map[int][]float64, []float64) { diff --git a/ethdb/kv_abstract.go b/ethdb/kv_abstract.go index a95ededfdedd377d3e448dd45d09a12b670a0baa..426b6319d126ec2807e43436360e04c28303f878 100644 --- a/ethdb/kv_abstract.go +++ b/ethdb/kv_abstract.go @@ -26,6 +26,8 @@ type Bucket interface { Put(key []byte, value []byte) error Delete(key []byte) error Cursor() Cursor + + Size() (uint64, error) } type Cursor interface { @@ -62,4 +64,5 @@ const ( Bolt DbProvider = iota Badger Remote + Lmdb ) diff --git a/ethdb/kv_badger.go b/ethdb/kv_badger.go index d493c06de0604e3f9b8c70a6fb7a5a8c9fab85dc..20da06a8c6f29b371616b50d2275ab4074941f7e 100644 --- a/ethdb/kv_badger.go +++ b/ethdb/kv_badger.go @@ -278,6 +278,10 @@ func (b badgerBucket) Delete(key []byte) error { return b.tx.badger.Delete(b.prefix) } +func (b badgerBucket) Size() (uint64, error) { + panic("not implemented") +} + func (b badgerBucket) Cursor() Cursor { c := badgerCursorPool.Get().(*badgerCursor) c.bucket = b diff --git a/ethdb/kv_bolt.go b/ethdb/kv_bolt.go index c8ea0daaf096be6a8216844b98d5cef0ba5b1fec..bd7ca0e109046aa405b69ab0028ee64bd5aa483c 100644 --- a/ethdb/kv_bolt.go +++ b/ethdb/kv_bolt.go @@ -3,6 +3,7 @@ package ethdb import ( "bytes" "context" + "os" "sync" "github.com/ledgerwatch/bolt" @@ -229,6 +230,11 @@ func (c *boltCursor) NoValues() NoValuesCursor { return &noValuesBoltCursor{boltCursor: c} } +func (b boltBucket) Size() (uint64, error) { + st := b.bolt.Stats() + return uint64((st.BranchPageN + st.BranchOverflowN + st.LeafPageN) * os.Getpagesize()), nil +} + func (b boltBucket) Get(key []byte) (val []byte, err error) { select { case <-b.tx.ctx.Done(): diff --git a/ethdb/kv_lmdb.go b/ethdb/kv_lmdb.go index 5501c3d5ccf38a2c8b32ceba9ae9b4590839195a..f91d966fd94d8957aec0514d2d783dd097e22c27 100644 --- a/ethdb/kv_lmdb.go +++ b/ethdb/kv_lmdb.go @@ -48,7 +48,6 @@ func (opts lmdbOpts) Open(ctx context.Context) (KV, error) { if err != nil { return nil, err } - err = env.SetMaxDBs(100) if err != nil { return nil, err @@ -369,6 +368,14 @@ func (b lmdbBucket) Delete(key []byte) error { return err } +func (b lmdbBucket) Size() (uint64, error) { + st, err := b.tx.tx.Stat(b.dbi) + if err != nil { + return 0, err + } + return (st.LeafPages + st.BranchPages + st.OverflowPages) * uint64(os.Getpagesize()), nil +} + func (b lmdbBucket) Cursor() Cursor { c := lmdbKvCursorPool.Get().(*lmdbCursor) c.ctx = b.tx.ctx diff --git a/ethdb/kv_remote.go b/ethdb/kv_remote.go index 4c65dcc257ba923e30db7116f4cd4aa821063598..11292a7c765f805fad210b9aafb5fe229c107d28 100644 --- a/ethdb/kv_remote.go +++ b/ethdb/kv_remote.go @@ -180,6 +180,10 @@ func (c *remoteCursor) NoValues() NoValuesCursor { return &remoteNoValuesCursor{remoteCursor: c} } +func (b remoteBucket) Size() (uint64, error) { + panic("not implemented") +} + func (b remoteBucket) Get(key []byte) (val []byte, err error) { val, err = b.remote.Get(key) return val, err