aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Morozov <lk4d4@docker.com>2016-01-28 09:51:40 -0800
committerAlexander Morozov <lk4d4@docker.com>2016-01-28 09:51:51 -0800
commite1ffca3629c16a5a19eebe8f7805176ce69cbf97 (patch)
treea2c36430ff48c4686bbae9e4aac1f2f10533370b
parentMerge pull request #492 from boltdb/revert-491-arm64 (diff)
downloaddedo-e1ffca3629c16a5a19eebe8f7805176ce69cbf97.tar.gz
dedo-e1ffca3629c16a5a19eebe8f7805176ce69cbf97.tar.xz
Use sync.Pool for small pages in db.allocate
Benchmark results: benchmark old ns/op new ns/op delta BenchmarkDBBatchAutomatic-4 2552625 2485200 -2.64% BenchmarkDBBatchSingle-4 59632698 50757603 -14.88% BenchmarkDBBatchManual10x100-4 2564789 2452735 -4.37% benchmark old allocs new allocs delta BenchmarkDBBatchAutomatic-4 10199 10202 +0.03% BenchmarkDBBatchSingle-4 56642 56653 +0.02% BenchmarkDBBatchManual10x100-4 5986 5995 +0.15% benchmark old bytes new bytes delta BenchmarkDBBatchAutomatic-4 433587 382462 -11.79% BenchmarkDBBatchSingle-4 32504533 16308931 -49.83% BenchmarkDBBatchManual10x100-4 1362370 881765 -35.28% Signed-off-by: Alexander Morozov <lk4d4@docker.com>
-rw-r--r--db.go18
-rw-r--r--tx.go16
2 files changed, 30 insertions, 4 deletions
diff --git a/db.go b/db.go
index 0f1e1bc..5d48709 100644
--- a/db.go
+++ b/db.go
@@ -36,6 +36,9 @@ const (
DefaultAllocSize = 16 * 1024 * 1024
)
+// default page size for db is set to the OS page size.
+var defaultPageSize = os.Getpagesize()
+
// DB represents a collection of buckets persisted to a file on disk.
// All data access is performed through transactions which can be obtained through the DB.
// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
@@ -320,7 +323,7 @@ func (db *DB) mmapSize(size int) (int, error) {
// init creates a new database file and initializes its meta pages.
func (db *DB) init() error {
// Set the page size to the OS page size.
- db.pageSize = os.Getpagesize()
+ db.pageSize = defaultPageSize
// Create two meta pages on a buffer.
buf := make([]byte, db.pageSize*4)
@@ -779,10 +782,21 @@ func (db *DB) meta() *meta {
return db.meta1
}
+var pagePool = sync.Pool{
+ New: func() interface{} {
+ return make([]byte, defaultPageSize)
+ },
+}
+
// allocate returns a contiguous block of memory starting at a given page.
func (db *DB) allocate(count int) (*page, error) {
// Allocate a temporary buffer for the page.
- buf := make([]byte, count*db.pageSize)
+ var buf []byte
+ if count == 1 && db.pageSize == defaultPageSize {
+ buf = pagePool.Get().([]byte)
+ } else {
+ buf = make([]byte, count*db.pageSize)
+ }
p := (*page)(unsafe.Pointer(&buf[0]))
p.overflow = uint32(count - 1)
diff --git a/tx.go b/tx.go
index e74d2ca..09a39fb 100644
--- a/tx.go
+++ b/tx.go
@@ -441,6 +441,8 @@ func (tx *Tx) write() error {
for _, p := range tx.pages {
pages = append(pages, p)
}
+ // Clear out page cache early.
+ tx.pages = make(map[pgid]*page)
sort.Sort(pages)
// Write pages to disk in order.
@@ -485,8 +487,18 @@ func (tx *Tx) write() error {
}
}
- // Clear out page cache.
- tx.pages = make(map[pgid]*page)
+ // put small pages back to sync.Pool
+ for _, p := range pages {
+ if int(p.overflow) != 0 || tx.db.pageSize != defaultPageSize {
+ continue
+ }
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:defaultPageSize]
+ // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1
+ for i := range buf {
+ buf[i] = 0
+ }
+ pagePool.Put(buf)
+ }
return nil
}