From e67705ed6348675b7bae405ebeb37bb69b53a96d Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Wed, 4 Nov 2015 15:12:18 -0800 Subject: do not grow dbsize agressively Only grow the database size when the high watermark increases. We also grows the database size a little bit aggressively to save a few ftruncates. I have tested this on various environments. The performance impact is ignorable with 16MB over allocation. Without over allocation, the performance might decrease 100% when each Tx.Commit needs a new page on a very slow disk (seek time dominates the total write). --- db.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'db.go') diff --git a/db.go b/db.go index d39c4aa..fd920a0 100644 --- a/db.go +++ b/db.go @@ -84,6 +84,7 @@ type DB struct { dataref []byte // mmap'ed readonly, write throws SEGV data *[maxMapSize]byte datasz int + filesz int // current on disk file size meta0 *meta meta1 *meta pageSize int @@ -655,6 +656,37 @@ func (db *DB) allocate(count int) (*page, error) { return p, nil } +// growSize grows the size of the database to the given sz. +func (db *DB) growSize(sz int) error { + if sz <= db.filesz { + return nil + } + + // over allocate 16MB to avoid calling Truncate aggressively + // for efficiency + overAllocation := 16 * 1024 * 1024 + sz = sz + overAllocation + + // do not over allocate + if sz > db.datasz { + sz = db.datasz + } + + // Truncate and fsync to ensure file size metadata is flushed. + // https://github.com/boltdb/bolt/issues/284 + if !db.NoGrowSync && !db.readOnly { + if err := db.file.Truncate(int64(sz)); err != nil { + return fmt.Errorf("file resize error: %s", err) + } + if err := db.file.Sync(); err != nil { + return fmt.Errorf("file sync error: %s", err) + } + } + + db.filesz = sz + return nil +} + func (db *DB) IsReadOnly() bool { return db.readOnly } -- cgit v1.2.3