aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db.go24
-rw-r--r--tx.go6
2 files changed, 20 insertions, 10 deletions
diff --git a/db.go b/db.go
index a4b8efb..911055d 100644
--- a/db.go
+++ b/db.go
@@ -33,6 +33,7 @@ const IgnoreNoSync = runtime.GOOS == "openbsd"
const (
DefaultMaxBatchSize int = 1000
DefaultMaxBatchDelay = 10 * time.Millisecond
+ DefaultAllocSize = 16 * 1024 * 1024
)
// DB represents a collection of buckets persisted to a file on disk.
@@ -85,6 +86,11 @@ type DB struct {
// Do not change concurrently with calls to Batch.
MaxBatchDelay time.Duration
+ // AllocSize is the amount of space allocated when the database
+ // needs to create new pages. This is done to amortize the cost
+ // of truncate() and fsync() when growing the data file.
+ AllocSize int
+
path string
file *os.File
dataref []byte // mmap'ed readonly, write throws SEGV
@@ -148,6 +154,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
// Set default values for later DB operations.
db.MaxBatchSize = DefaultMaxBatchSize
db.MaxBatchDelay = DefaultMaxBatchDelay
+ db.AllocSize = DefaultAllocSize
flag := os.O_RDWR
if options.ReadOnly {
@@ -799,20 +806,19 @@ 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 {
+// grow grows the size of the database to the given sz.
+func (db *DB) grow(sz int) error {
+ // Ignore if the new size is less than available file size.
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 {
+ // If the data is smaller than the alloc size then only allocate what's needed.
+ // Once it goes over the allocation size then allocate in chunks.
+ if db.datasz < db.AllocSize {
sz = db.datasz
+ } else {
+ sz += db.AllocSize
}
// Truncate and fsync to ensure file size metadata is flushed.
diff --git a/tx.go b/tx.go
index 395dce3..52b68ef 100644
--- a/tx.go
+++ b/tx.go
@@ -184,8 +184,12 @@ func (tx *Tx) Commit() error {
}
tx.meta.freelist = p.id
+ // If the high water mark has moved up then attempt to grow the database.
if tx.meta.pgid > opgid {
- tx.db.growSize(int(tx.meta.pgid+1) * tx.db.pageSize)
+ if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil {
+ tx.rollback()
+ return err
+ }
}
// Write dirty pages to disk.