aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bucket.go40
-rw-r--r--bucket_test.go78
2 files changed, 85 insertions, 33 deletions
diff --git a/bucket.go b/bucket.go
index 77d31c9..c429842 100644
--- a/bucket.go
+++ b/bucket.go
@@ -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
})
})