From c105316292b7aef09c1eb260fb5f5c8f9f07ec3f Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 17 Jun 2014 18:40:56 +0000 Subject: [PATCH 1/2] add freelist stats to db stats --- db.go | 22 ++++++++++++++++------ db_test.go | 3 ++- freelist.go | 11 ++++++++++- tx.go | 4 +--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/db.go b/db.go index 0b4631f..f58da8c 100644 --- a/db.go +++ b/db.go @@ -427,16 +427,12 @@ func (db *DB) removeTx(tx *Tx) { break } } - n := len(db.txs) // Unlock the meta pages. db.metalock.Unlock() // Merge statistics. - db.statlock.Lock() - db.stats.OpenTxN = n - db.stats.TxStats.add(&tx.stats) - db.statlock.Unlock() + db.mergeStats(&tx.stats) } // Update executes a function within the context of a read-write managed transaction. @@ -554,10 +550,24 @@ func (db *DB) allocate(count int) (*page, error) { return p, nil } +// mergeStats updates db stats in thread-safe manner. +func (db *DB) mergeStats(txStats *TxStats) { + db.statlock.Lock() + db.stats.FreelistN = db.freelist.count() + db.stats.FreelistAlloc = db.freelist.size() + db.stats.OpenTxN = len(db.txs) + db.stats.TxStats.add(txStats) + db.statlock.Unlock() +} + // Stats represents statistics about the database. type Stats struct { + // Freelist stats + FreelistN int // total number of pages on the freelist + FreelistAlloc int // total bytes used by the freelist and the pages on it + // Transaction stats - TxN int // total number of completed read transactions + TxN int // total number of started read transactions OpenTxN int // number of currently open read transactions TxStats TxStats // global, ongoing stats. diff --git a/db_test.go b/db_test.go index 9fd4662..8e9f399 100644 --- a/db_test.go +++ b/db_test.go @@ -253,7 +253,8 @@ func TestDB_Stats(t *testing.T) { return err }) stats := db.Stats() - assert.Equal(t, 2, stats.TxStats.PageCount) + assert.Equal(t, 2, stats.TxStats.PageCount, "PageCount") + assert.Equal(t, 2, stats.FreelistN, "FreelistN %d", db.freelist.count()) }) } diff --git a/freelist.go b/freelist.go index e27f80a..3551113 100644 --- a/freelist.go +++ b/freelist.go @@ -22,7 +22,16 @@ type freelist struct { // size returns the size of the page after serialization. func (f *freelist) size() int { - return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * len(f.all())) + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count()) +} + +// count returns count of pages on the freelist +func (f *freelist) count() int { + var count = len(f.ids) + for _, list := range f.pending { + count += len(list) + } + return count } // all returns a list of all free ids and all pending ids in one sorted list. diff --git a/tx.go b/tx.go index 9ab1178..5cb99e0 100644 --- a/tx.go +++ b/tx.go @@ -236,9 +236,7 @@ func (tx *Tx) close() { tx.db.rwlock.Unlock() // Merge statistics. - tx.db.statlock.Lock() - tx.db.stats.TxStats.add(&tx.stats) - tx.db.statlock.Unlock() + tx.db.mergeStats(&tx.stats) } else { tx.db.removeTx(tx) } From 4918ce83018aef9d80e3c9ed2035b22dd5cddac9 Mon Sep 17 00:00:00 2001 From: Martin Kobetic Date: Tue, 17 Jun 2014 19:30:10 +0000 Subject: [PATCH 2/2] drop mergeStats and move freelist stats update to Tx --- db.go | 16 +++++----------- tx.go | 10 +++++++++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/db.go b/db.go index f58da8c..13bfb16 100644 --- a/db.go +++ b/db.go @@ -427,12 +427,16 @@ func (db *DB) removeTx(tx *Tx) { break } } + n := len(db.txs) // Unlock the meta pages. db.metalock.Unlock() // Merge statistics. - db.mergeStats(&tx.stats) + db.statlock.Lock() + db.stats.OpenTxN = n + db.stats.TxStats.add(&tx.stats) + db.statlock.Unlock() } // Update executes a function within the context of a read-write managed transaction. @@ -550,16 +554,6 @@ func (db *DB) allocate(count int) (*page, error) { return p, nil } -// mergeStats updates db stats in thread-safe manner. -func (db *DB) mergeStats(txStats *TxStats) { - db.statlock.Lock() - db.stats.FreelistN = db.freelist.count() - db.stats.FreelistAlloc = db.freelist.size() - db.stats.OpenTxN = len(db.txs) - db.stats.TxStats.add(txStats) - db.statlock.Unlock() -} - // Stats represents statistics about the database. type Stats struct { // Freelist stats diff --git a/tx.go b/tx.go index 5cb99e0..bcbcd5f 100644 --- a/tx.go +++ b/tx.go @@ -232,11 +232,19 @@ func (tx *Tx) rollback() { func (tx *Tx) close() { if tx.writable { + // Grab freelist stats. + var freelistN = tx.db.freelist.count() + var freelistAlloc = tx.db.freelist.size() + // Remove writer lock. tx.db.rwlock.Unlock() // Merge statistics. - tx.db.mergeStats(&tx.stats) + tx.db.statlock.Lock() + tx.db.stats.FreelistN = freelistN + tx.db.stats.FreelistAlloc = freelistAlloc + tx.db.stats.TxStats.add(&tx.stats) + tx.db.statlock.Unlock() } else { tx.db.removeTx(tx) }