From 382ccc27461413f8e47d4db3016f8a1a20aa0617 Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 18:22:42 +0000 Subject: add Used/Free Leaf/Branch bucket stats --- bucket.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bucket.go b/bucket.go index 77d31c9..5f78710 100644 --- a/bucket.go +++ b/bucket.go @@ -331,12 +331,23 @@ 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().Info().PageSize b.tx.forEachPage(b.root, 0, func(p *page, depth int) { if (p.flags & leafPageFlag) != 0 { s.LeafPageCount++ s.KeyCount += 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.UsedLeafSpace += used + s.FreeLeafSpace += int(p.overflow+1)*pageSize - used } else if (p.flags & branchPageFlag) != 0 { s.BranchPageCount++ + lastElement := p.branchPageElement(p.count - 1) + used := pageHeaderSize + (branchPageElementSize * int(p.count-1)) + used += int(lastElement.pos + lastElement.ksize) + s.UsedBranchSpace += used + s.FreeBranchSpace += int(p.overflow+1)*pageSize - used } s.OverflowPageCount += int(p.overflow) @@ -511,4 +522,8 @@ type BucketStat struct { OverflowPageCount int KeyCount int MaxDepth int + UsedBranchSpace int + FreeBranchSpace int + UsedLeafSpace int + FreeLeafSpace int } -- cgit v1.2.3 From 9c1b76818501e93527740c59b553547c892e9c1f Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 18:34:34 +0000 Subject: update stats test --- bucket_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bucket_test.go b/bucket_test.go index 421b942..eccbf56 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -501,6 +501,10 @@ func TestBucket_Stat(t *testing.T) { assert.Equal(t, stat.OverflowPageCount, 2) assert.Equal(t, stat.KeyCount, 501) assert.Equal(t, stat.MaxDepth, 2) + assert.Equal(t, stat.UsedBranchSpace, 125) + assert.Equal(t, stat.FreeBranchSpace, 3971) + assert.Equal(t, stat.UsedLeafSpace, 20908) + assert.Equal(t, stat.FreeLeafSpace, 11860) b = tx.Bucket([]byte("whozawhats")) stat = b.Stat() @@ -509,6 +513,10 @@ func TestBucket_Stat(t *testing.T) { assert.Equal(t, stat.OverflowPageCount, 0) assert.Equal(t, stat.KeyCount, 1) assert.Equal(t, stat.MaxDepth, 1) + assert.Equal(t, stat.UsedBranchSpace, 0) + assert.Equal(t, stat.FreeBranchSpace, 0) + assert.Equal(t, stat.UsedLeafSpace, 38) + assert.Equal(t, stat.FreeLeafSpace, 4058) return nil }) -- cgit v1.2.3 From 62592ec84021a21b35b43b39cdeaebbd740f6c0d Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 20:18:09 +0000 Subject: moar tweaks --- bucket.go | 33 +++++++++++++++++---------------- bucket_test.go | 56 ++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/bucket.go b/bucket.go index 5f78710..d4609e4 100644 --- a/bucket.go +++ b/bucket.go @@ -331,7 +331,7 @@ 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().Info().PageSize + pageSize := b.tx.db.pageSize b.tx.forEachPage(b.root, 0, func(p *page, depth int) { if (p.flags & leafPageFlag) != 0 { s.LeafPageCount++ @@ -339,23 +339,23 @@ func (b *Bucket) Stat() *BucketStat { lastElement := p.leafPageElement(p.count - 1) used := pageHeaderSize + (leafPageElementSize * int(p.count-1)) used += int(lastElement.pos + lastElement.ksize + lastElement.vsize) - s.UsedLeafSpace += used - s.FreeLeafSpace += int(p.overflow+1)*pageSize - used + s.LeafInuse += used + s.LeafOverflowPageCount += int(p.overflow) } else if (p.flags & branchPageFlag) != 0 { s.BranchPageCount++ lastElement := p.branchPageElement(p.count - 1) used := pageHeaderSize + (branchPageElementSize * int(p.count-1)) used += int(lastElement.pos + lastElement.ksize) - s.UsedBranchSpace += used - s.FreeBranchSpace += int(p.overflow+1)*pageSize - used + s.BranchInuse += used + s.BranchOverflowPageCount += int(p.overflow) } - s.OverflowPageCount += int(p.overflow) - if depth+1 > s.MaxDepth { s.MaxDepth = (depth + 1) } }) + s.BranchAlloc = (s.BranchPageCount + s.BranchOverflowPageCount) * pageSize + s.LeafAlloc = (s.LeafPageCount + s.LeafOverflowPageCount) * pageSize return s } @@ -517,13 +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 - UsedBranchSpace int - FreeBranchSpace int - UsedLeafSpace int - FreeLeafSpace int + BranchPageCount int + BranchOverflowPageCount int + LeafPageCount int + LeafOverflowPageCount int + KeyCount int + MaxDepth int + BranchAlloc int + BranchInuse int + LeafAlloc int + LeafInuse int } diff --git a/bucket_test.go b/bucket_test.go index eccbf56..b9238e2 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -485,11 +485,6 @@ func TestBucket_Stat(t *testing.T) { } b.Put([]byte("really-big-value"), []byte(strings.Repeat("*", 10000))) - // Add a bucket that fits on a single root leaf. - b, err = tx.CreateBucket([]byte("whozawhats")) - assert.NoError(t, err) - b.Put([]byte("foo"), []byte("bar")) - return nil }) mustCheck(db) @@ -497,26 +492,46 @@ func TestBucket_Stat(t *testing.T) { b := tx.Bucket([]byte("woojits")) stat := b.Stat() assert.Equal(t, stat.BranchPageCount, 1) + assert.Equal(t, stat.BranchOverflowPageCount, 0) assert.Equal(t, stat.LeafPageCount, 6) - assert.Equal(t, stat.OverflowPageCount, 2) + assert.Equal(t, stat.LeafOverflowPageCount, 2) assert.Equal(t, stat.KeyCount, 501) assert.Equal(t, stat.MaxDepth, 2) - assert.Equal(t, stat.UsedBranchSpace, 125) - assert.Equal(t, stat.FreeBranchSpace, 3971) - assert.Equal(t, stat.UsedLeafSpace, 20908) - assert.Equal(t, stat.FreeLeafSpace, 11860) + assert.Equal(t, stat.BranchInuse, 125) + assert.Equal(t, stat.BranchAlloc, 4096) + assert.Equal(t, stat.LeafInuse, 20908) + assert.Equal(t, stat.LeafAlloc, 32768) - b = tx.Bucket([]byte("whozawhats")) - stat = b.Stat() + 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")) + assert.NoError(t, err) + b.Put([]byte("foo"), []byte("bar")) + + return nil + }) + mustCheck(db) + db.View(func(tx *Tx) error { + b := tx.Bucket([]byte("whozawhats")) + stat := b.Stat() assert.Equal(t, stat.BranchPageCount, 0) + assert.Equal(t, stat.BranchOverflowPageCount, 0) assert.Equal(t, stat.LeafPageCount, 1) - assert.Equal(t, stat.OverflowPageCount, 0) + assert.Equal(t, stat.LeafOverflowPageCount, 0) assert.Equal(t, stat.KeyCount, 1) assert.Equal(t, stat.MaxDepth, 1) - assert.Equal(t, stat.UsedBranchSpace, 0) - assert.Equal(t, stat.FreeBranchSpace, 0) - assert.Equal(t, stat.UsedLeafSpace, 38) - assert.Equal(t, stat.FreeLeafSpace, 4058) + 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 }) @@ -544,10 +559,15 @@ func TestBucket_Stat_Large(t *testing.T) { b := tx.Bucket([]byte("widgets")) stat := b.Stat() assert.Equal(t, stat.BranchPageCount, 15) + assert.Equal(t, stat.BranchOverflowPageCount, 0) assert.Equal(t, stat.LeafPageCount, 1281) - assert.Equal(t, stat.OverflowPageCount, 0) + assert.Equal(t, stat.LeafOverflowPageCount, 0) assert.Equal(t, stat.KeyCount, 100000) assert.Equal(t, stat.MaxDepth, 3) + 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 }) }) -- cgit v1.2.3 From 4245fd9c4eac97fb01d1b75bb637bbdb5f4e1952 Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 20:22:18 +0000 Subject: allign naming with MemStats --- bucket.go | 34 +++++++++++++++++----------------- bucket_test.go | 30 +++++++++++++++--------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bucket.go b/bucket.go index d4609e4..1b8722d 100644 --- a/bucket.go +++ b/bucket.go @@ -334,28 +334,28 @@ func (b *Bucket) Stat() *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.LeafOverflowPageCount += int(p.overflow) + 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.BranchOverflowPageCount += int(p.overflow) + s.BranchOverflowN += int(p.overflow) } if depth+1 > s.MaxDepth { s.MaxDepth = (depth + 1) } }) - s.BranchAlloc = (s.BranchPageCount + s.BranchOverflowPageCount) * pageSize - s.LeafAlloc = (s.LeafPageCount + s.LeafOverflowPageCount) * pageSize + s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize + s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize return s } @@ -517,14 +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 - BranchOverflowPageCount int - LeafPageCount int - LeafOverflowPageCount int - KeyCount int - MaxDepth int - BranchAlloc int - BranchInuse int - LeafAlloc int - LeafInuse int + BranchPageN int + BranchOverflowN int + LeafPageN int + LeafOverflowN int + KeyN int + MaxDepth int + BranchAlloc int + BranchInuse int + LeafAlloc int + LeafInuse int } diff --git a/bucket_test.go b/bucket_test.go index b9238e2..34dadab 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -491,11 +491,11 @@ func TestBucket_Stat(t *testing.T) { db.View(func(tx *Tx) error { b := tx.Bucket([]byte("woojits")) stat := b.Stat() - assert.Equal(t, stat.BranchPageCount, 1) - assert.Equal(t, stat.BranchOverflowPageCount, 0) - assert.Equal(t, stat.LeafPageCount, 6) - assert.Equal(t, stat.LeafOverflowPageCount, 2) - assert.Equal(t, stat.KeyCount, 501) + 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.MaxDepth, 2) assert.Equal(t, stat.BranchInuse, 125) assert.Equal(t, stat.BranchAlloc, 4096) @@ -522,11 +522,11 @@ func TestBucket_Stat_Small(t *testing.T) { db.View(func(tx *Tx) error { b := tx.Bucket([]byte("whozawhats")) stat := b.Stat() - assert.Equal(t, stat.BranchPageCount, 0) - assert.Equal(t, stat.BranchOverflowPageCount, 0) - assert.Equal(t, stat.LeafPageCount, 1) - assert.Equal(t, stat.LeafOverflowPageCount, 0) - assert.Equal(t, stat.KeyCount, 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.MaxDepth, 1) assert.Equal(t, stat.BranchInuse, 0) assert.Equal(t, stat.BranchAlloc, 0) @@ -558,11 +558,11 @@ 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.BranchOverflowPageCount, 0) - assert.Equal(t, stat.LeafPageCount, 1281) - assert.Equal(t, stat.LeafOverflowPageCount, 0) - assert.Equal(t, stat.KeyCount, 100000) + 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.MaxDepth, 3) assert.Equal(t, stat.BranchInuse, 27289) assert.Equal(t, stat.BranchAlloc, 61440) -- cgit v1.2.3 From 03cb096230fb8d4a1d90667f87be7d168934931d Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 20:29:37 +0000 Subject: skip space assertions for incompatible page size --- bucket_test.go | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/bucket_test.go b/bucket_test.go index 34dadab..740afd8 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -497,11 +497,13 @@ func TestBucket_Stat(t *testing.T) { assert.Equal(t, stat.LeafOverflowN, 2) assert.Equal(t, stat.KeyN, 501) assert.Equal(t, stat.MaxDepth, 2) - assert.Equal(t, stat.BranchInuse, 125) - assert.Equal(t, stat.BranchAlloc, 4096) - assert.Equal(t, stat.LeafInuse, 20908) - assert.Equal(t, stat.LeafAlloc, 32768) - + 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 }) }) @@ -509,6 +511,7 @@ func TestBucket_Stat(t *testing.T) { // 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. @@ -528,11 +531,13 @@ func TestBucket_Stat_Small(t *testing.T) { assert.Equal(t, stat.LeafOverflowN, 0) assert.Equal(t, stat.KeyN, 1) assert.Equal(t, stat.MaxDepth, 1) - assert.Equal(t, stat.BranchInuse, 0) - assert.Equal(t, stat.BranchAlloc, 0) - assert.Equal(t, stat.LeafInuse, 38) - assert.Equal(t, stat.LeafAlloc, 4096) - + 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 }) }) @@ -564,10 +569,13 @@ func TestBucket_Stat_Large(t *testing.T) { assert.Equal(t, stat.LeafOverflowN, 0) assert.Equal(t, stat.KeyN, 100000) assert.Equal(t, stat.MaxDepth, 3) - assert.Equal(t, stat.BranchInuse, 27289) - assert.Equal(t, stat.BranchAlloc, 61440) - assert.Equal(t, stat.LeafInuse, 2598276) - assert.Equal(t, stat.LeafAlloc, 5246976) + 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 }) }) -- cgit v1.2.3 From a02ddf402bbfde5a2d6e8a26bae188527e157634 Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 22 Apr 2014 20:32:09 +0000 Subject: rename MaxDepth to Depth --- bucket.go | 6 +++--- bucket_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bucket.go b/bucket.go index 1b8722d..c429842 100644 --- a/bucket.go +++ b/bucket.go @@ -350,8 +350,8 @@ func (b *Bucket) Stat() *BucketStat { s.BranchOverflowN += 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 @@ -522,7 +522,7 @@ type BucketStat struct { LeafPageN int LeafOverflowN int KeyN int - MaxDepth int + Depth int BranchAlloc int BranchInuse int LeafAlloc int diff --git a/bucket_test.go b/bucket_test.go index 740afd8..33f0f31 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -496,7 +496,7 @@ func TestBucket_Stat(t *testing.T) { assert.Equal(t, stat.LeafPageN, 6) assert.Equal(t, stat.LeafOverflowN, 2) assert.Equal(t, stat.KeyN, 501) - assert.Equal(t, stat.MaxDepth, 2) + assert.Equal(t, stat.Depth, 2) if os.Getpagesize() != 4096 { // Incompatible page size assert.Equal(t, stat.BranchInuse, 125) @@ -530,7 +530,7 @@ func TestBucket_Stat_Small(t *testing.T) { assert.Equal(t, stat.LeafPageN, 1) assert.Equal(t, stat.LeafOverflowN, 0) assert.Equal(t, stat.KeyN, 1) - assert.Equal(t, stat.MaxDepth, 1) + assert.Equal(t, stat.Depth, 1) if os.Getpagesize() != 4096 { // Incompatible page size assert.Equal(t, stat.BranchInuse, 0) @@ -568,7 +568,7 @@ func TestBucket_Stat_Large(t *testing.T) { assert.Equal(t, stat.LeafPageN, 1281) assert.Equal(t, stat.LeafOverflowN, 0) assert.Equal(t, stat.KeyN, 100000) - assert.Equal(t, stat.MaxDepth, 3) + assert.Equal(t, stat.Depth, 3) if os.Getpagesize() != 4096 { // Incompatible page size assert.Equal(t, stat.BranchInuse, 27289) -- cgit v1.2.3