diff options
-rw-r--r-- | bucket.go | 40 | ||||
-rw-r--r-- | bucket_test.go | 78 |
2 files changed, 85 insertions, 33 deletions
@@ -331,20 +331,31 @@ func (b *Bucket) ForEach(fn func(k, v []byte) error) error { // Stat returns stats on a bucket. func (b *Bucket) Stat() *BucketStat { s := &BucketStat{} + pageSize := b.tx.db.pageSize b.tx.forEachPage(b.root, 0, func(p *page, depth int) { if (p.flags & leafPageFlag) != 0 { - s.LeafPageCount++ - s.KeyCount += int(p.count) + s.LeafPageN++ + s.KeyN += int(p.count) + lastElement := p.leafPageElement(p.count - 1) + used := pageHeaderSize + (leafPageElementSize * int(p.count-1)) + used += int(lastElement.pos + lastElement.ksize + lastElement.vsize) + s.LeafInuse += used + s.LeafOverflowN += int(p.overflow) } else if (p.flags & branchPageFlag) != 0 { - s.BranchPageCount++ + s.BranchPageN++ + lastElement := p.branchPageElement(p.count - 1) + used := pageHeaderSize + (branchPageElementSize * int(p.count-1)) + used += int(lastElement.pos + lastElement.ksize) + s.BranchInuse += used + s.BranchOverflowN += int(p.overflow) } - s.OverflowPageCount += int(p.overflow) - - if depth+1 > s.MaxDepth { - s.MaxDepth = (depth + 1) + if depth+1 > s.Depth { + s.Depth = (depth + 1) } }) + s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize + s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize return s } @@ -506,9 +517,14 @@ func (b *Bucket) pageNode(id pgid) (*page, *node) { // BucketStat represents stats on a bucket such as branch pages and leaf pages. type BucketStat struct { - BranchPageCount int - LeafPageCount int - OverflowPageCount int - KeyCount int - MaxDepth int + BranchPageN int + BranchOverflowN int + LeafPageN int + LeafOverflowN int + KeyN int + Depth int + BranchAlloc int + BranchInuse int + LeafAlloc int + LeafInuse int } diff --git a/bucket_test.go b/bucket_test.go index 421b942..33f0f31 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -485,8 +485,37 @@ func TestBucket_Stat(t *testing.T) { } b.Put([]byte("really-big-value"), []byte(strings.Repeat("*", 10000))) + return nil + }) + mustCheck(db) + db.View(func(tx *Tx) error { + b := tx.Bucket([]byte("woojits")) + stat := b.Stat() + assert.Equal(t, stat.BranchPageN, 1) + assert.Equal(t, stat.BranchOverflowN, 0) + assert.Equal(t, stat.LeafPageN, 6) + assert.Equal(t, stat.LeafOverflowN, 2) + assert.Equal(t, stat.KeyN, 501) + assert.Equal(t, stat.Depth, 2) + if os.Getpagesize() != 4096 { + // Incompatible page size + assert.Equal(t, stat.BranchInuse, 125) + assert.Equal(t, stat.BranchAlloc, 4096) + assert.Equal(t, stat.LeafInuse, 20908) + assert.Equal(t, stat.LeafAlloc, 32768) + } + return nil + }) + }) +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stat_Small(t *testing.T) { + + withOpenDB(func(db *DB, path string) { + db.Update(func(tx *Tx) error { // Add a bucket that fits on a single root leaf. - b, err = tx.CreateBucket([]byte("whozawhats")) + b, err := tx.CreateBucket([]byte("whozawhats")) assert.NoError(t, err) b.Put([]byte("foo"), []byte("bar")) @@ -494,22 +523,21 @@ func TestBucket_Stat(t *testing.T) { }) mustCheck(db) db.View(func(tx *Tx) error { - b := tx.Bucket([]byte("woojits")) + b := tx.Bucket([]byte("whozawhats")) stat := b.Stat() - assert.Equal(t, stat.BranchPageCount, 1) - assert.Equal(t, stat.LeafPageCount, 6) - assert.Equal(t, stat.OverflowPageCount, 2) - assert.Equal(t, stat.KeyCount, 501) - assert.Equal(t, stat.MaxDepth, 2) - - b = tx.Bucket([]byte("whozawhats")) - stat = b.Stat() - assert.Equal(t, stat.BranchPageCount, 0) - assert.Equal(t, stat.LeafPageCount, 1) - assert.Equal(t, stat.OverflowPageCount, 0) - assert.Equal(t, stat.KeyCount, 1) - assert.Equal(t, stat.MaxDepth, 1) - + assert.Equal(t, stat.BranchPageN, 0) + assert.Equal(t, stat.BranchOverflowN, 0) + assert.Equal(t, stat.LeafPageN, 1) + assert.Equal(t, stat.LeafOverflowN, 0) + assert.Equal(t, stat.KeyN, 1) + assert.Equal(t, stat.Depth, 1) + if os.Getpagesize() != 4096 { + // Incompatible page size + assert.Equal(t, stat.BranchInuse, 0) + assert.Equal(t, stat.BranchAlloc, 0) + assert.Equal(t, stat.LeafInuse, 38) + assert.Equal(t, stat.LeafAlloc, 4096) + } return nil }) }) @@ -535,11 +563,19 @@ func TestBucket_Stat_Large(t *testing.T) { db.View(func(tx *Tx) error { b := tx.Bucket([]byte("widgets")) stat := b.Stat() - assert.Equal(t, stat.BranchPageCount, 15) - assert.Equal(t, stat.LeafPageCount, 1281) - assert.Equal(t, stat.OverflowPageCount, 0) - assert.Equal(t, stat.KeyCount, 100000) - assert.Equal(t, stat.MaxDepth, 3) + assert.Equal(t, stat.BranchPageN, 15) + assert.Equal(t, stat.BranchOverflowN, 0) + assert.Equal(t, stat.LeafPageN, 1281) + assert.Equal(t, stat.LeafOverflowN, 0) + assert.Equal(t, stat.KeyN, 100000) + assert.Equal(t, stat.Depth, 3) + if os.Getpagesize() != 4096 { + // Incompatible page size + assert.Equal(t, stat.BranchInuse, 27289) + assert.Equal(t, stat.BranchAlloc, 61440) + assert.Equal(t, stat.LeafInuse, 2598276) + assert.Equal(t, stat.LeafAlloc, 5246976) + } return nil }) }) |