Add option to adjust fill percentage.

This commit adds the ability to adjust the fill percentage for splitting nodes. This
works by setting a threshold that is a percentage of a total page size. When that
threshold is crossed during a split then a new node is created.

This is primarily beneficial for append-only workloads.

Fixes #163.
pull/34/head
Ben Johnson 2014-05-15 14:04:57 -06:00
parent 7b96ede8b6
commit a1873dd6f6
4 changed files with 28 additions and 3 deletions

View File

@ -46,6 +46,7 @@ func Bench(options *BenchOptions) {
fatal(err)
return
}
db.FillPercent = options.FillPercent
defer db.Close()
// Enable streaming stats.
@ -280,6 +281,7 @@ type BenchOptions struct {
MemProfile string
BlockProfile string
StatsInterval time.Duration
FillPercent float64
Clean bool
}

View File

@ -8,6 +8,7 @@ import (
"os"
"time"
"github.com/boltdb/bolt"
"github.com/codegangsta/cli"
)
@ -114,6 +115,7 @@ func NewApp() *cli.App {
&cli.StringFlag{Name: "memprofile", Usage: "Memory profile output path"},
&cli.StringFlag{Name: "blockprofile", Usage: "Block profile output path"},
&cli.StringFlag{Name: "stats-interval", Value: "0s", Usage: "Continuous stats interval"},
&cli.Float64Flag{Name: "fill-percent", Value: bolt.DefaultFillPercent, Usage: "Fill percentage"},
&cli.BoolFlag{Name: "work", Usage: "Print the temp db and do not delete on exit"},
},
Action: func(c *cli.Context) {
@ -134,6 +136,7 @@ func NewApp() *cli.App {
MemProfile: c.String("memprofile"),
BlockProfile: c.String("blockprofile"),
StatsInterval: statsInterval,
FillPercent: c.Float64("fill-percent"),
Clean: !c.Bool("work"),
})
},

16
db.go
View File

@ -24,6 +24,15 @@ const version = 2
// Represents a marker value to indicate that a file is a Bolt DB.
const magic uint32 = 0xED0CDAED
const (
minFillPercent = 0.1
maxFillPercent = 1.0
)
// DefaultFillPercent is the percentage that split pages are filled.
// This value can be changed by setting DB.FillPercent.
const DefaultFillPercent = 0.5
var (
// ErrDatabaseNotOpen is returned when a DB instance is accessed before it
// is opened or after it is closed.
@ -54,6 +63,11 @@ type DB struct {
// debugging purposes.
StrictMode bool
// Sets the threshold for filling pages when they split. By default,
// the database will fill to 50% but it can be useful to increase this
// amount if you know that your write workloads are typically append-only.
FillPercent float64
path string
file *os.File
data []byte
@ -94,7 +108,7 @@ func (db *DB) String() string {
// Open creates and opens a database at the given path.
// If the file does not exist then it will be created automatically.
func Open(path string, mode os.FileMode) (*DB, error) {
var db = &DB{opened: true}
var db = &DB{opened: true, FillPercent: DefaultFillPercent}
// Open data file and separate sync handler for metadata writes.
db.path = path

10
node.go
View File

@ -215,8 +215,14 @@ func (n *node) split(pageSize int) []*node {
return nodes
}
// Set fill threshold to 50%.
threshold := pageSize / 2
// Determine the threshold before starting a new node.
var fillPercent = n.bucket.tx.db.FillPercent
if fillPercent < minFillPercent {
fillPercent = minFillPercent
} else if fillPercent > maxFillPercent {
fillPercent = maxFillPercent
}
threshold := int(float64(pageSize) * fillPercent)
// Group into smaller pages and target a given fill size.
size := pageHeaderSize