Skip to content

Commit 3a21e18

Browse files
tjungblumrueg
andcommitted
Improve memory alignment
This runs betteralign to pack structs smarter. Originally proposed by #673 Co-authored-by: Manuel Rüger <[email protected]> Signed-off-by: Thomas Jungblut <[email protected]>
1 parent b342624 commit 3a21e18

File tree

8 files changed

+109
-104
lines changed

8 files changed

+109
-104
lines changed

bucket.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,6 @@ func cloneBytes(v []byte) []byte {
10001000

10011001
type BucketStructure struct {
10021002
Name string `json:"name"` // name of the bucket
1003-
KeyN int `json:"keyN"` // number of key/value pairs
10041003
Children []BucketStructure `json:"buckets,omitempty"` // child buckets
1004+
KeyN int `json:"keyN"` // number of key/value pairs
10051005
}

cmd/bbolt/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,10 @@ func newPageItemCommand(m *Main) *pageItemCommand {
369369
}
370370

371371
type pageItemOptions struct {
372+
format string
372373
help bool
373374
keyOnly bool
374375
valueOnly bool
375-
format string
376376
}
377377

378378
// Run executes the command.
@@ -1597,8 +1597,8 @@ func (r *BenchResults) OpsPerSecond() int {
15971597
}
15981598

15991599
type PageError struct {
1600-
ID int
16011600
Err error
1601+
ID int
16021602
}
16031603

16041604
func (e *PageError) Error() string {

db.go

+93-88
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,23 @@ type DB struct {
4242
// refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
4343
stats Stats
4444

45-
// When enabled, the database will perform a Check() after every commit.
46-
// A panic is issued if the database is in an inconsistent state. This
47-
// flag has a large performance impact so it should only be used for
48-
// debugging purposes.
49-
StrictMode bool
45+
pagePool sync.Pool
5046

51-
// Setting the NoSync flag will cause the database to skip fsync()
52-
// calls after each commit. This can be useful when bulk loading data
53-
// into a database and you can restart the bulk load in the event of
54-
// a system failure or database corruption. Do not set this flag for
55-
// normal use.
56-
//
57-
// If the package global IgnoreNoSync constant is true, this value is
58-
// ignored. See the comment on that constant for more details.
59-
//
60-
// THIS IS UNSAFE. PLEASE USE WITH CAUTION.
61-
NoSync bool
47+
logger Logger
6248

63-
// When true, skips syncing freelist to disk. This improves the database
64-
// write performance under normal operation, but requires a full database
65-
// re-sync during recovery.
66-
NoFreelistSync bool
49+
openFile func(string, int, os.FileMode) (*os.File, error)
50+
file *os.File
51+
data *[maxMapSize]byte
52+
meta0 *common.Meta
53+
meta1 *common.Meta
54+
rwtx *Tx
55+
56+
freelist *freelist
57+
batch *batch
58+
59+
ops struct {
60+
writeAt func(b []byte, off int64) (n int, err error)
61+
}
6762

6863
// FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
6964
// dramatic performance degradation if database is large and fragmentation in freelist is common.
@@ -72,18 +67,12 @@ type DB struct {
7267
// The default type is array
7368
FreelistType FreelistType
7469

75-
// When true, skips the truncate call when growing the database.
76-
// Setting this to true is only safe on non-ext3/ext4 systems.
77-
// Skipping truncation avoids preallocation of hard drive space and
78-
// bypasses a truncate() and fsync() syscall on remapping.
79-
//
80-
// https://github.com/boltdb/bolt/issues/284
81-
NoGrowSync bool
82-
83-
// When `true`, bbolt will always load the free pages when opening the DB.
84-
// When opening db in write mode, this flag will always automatically
85-
// set to `true`.
86-
PreLoadFreelist bool
70+
path string
71+
// `dataref` isn't used at all on Windows, and the golangci-lint
72+
// always fails on Windows platform.
73+
//nolint
74+
dataref []byte // mmap'ed readonly, write throws SEGV
75+
txs []*Tx
8776

8877
// If you want to read the entire database fast, you can set MmapFlag to
8978
// syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead.
@@ -110,46 +99,61 @@ type DB struct {
11099
// of truncate() and fsync() when growing the data file.
111100
AllocSize int
112101

113-
// Mlock locks database file in memory when set to true.
114-
// It prevents major page faults, however used memory can't be reclaimed.
115-
//
116-
// Supported only on Unix via mlock/munlock syscalls.
117-
Mlock bool
118-
119-
logger Logger
120-
121-
path string
122-
openFile func(string, int, os.FileMode) (*os.File, error)
123-
file *os.File
124-
// `dataref` isn't used at all on Windows, and the golangci-lint
125-
// always fails on Windows platform.
126-
//nolint
127-
dataref []byte // mmap'ed readonly, write throws SEGV
128-
data *[maxMapSize]byte
129102
datasz int
130-
meta0 *common.Meta
131-
meta1 *common.Meta
132103
pageSize int
133-
opened bool
134-
rwtx *Tx
135-
txs []*Tx
104+
mmaplock sync.RWMutex // Protects mmap access during remapping.
105+
statlock sync.RWMutex // Protects stats access.
136106

137-
freelist *freelist
138107
freelistLoad sync.Once
139108

140-
pagePool sync.Pool
141-
142109
batchMu sync.Mutex
143-
batch *batch
144110

145-
rwlock sync.Mutex // Allows only one writer at a time.
146-
metalock sync.Mutex // Protects meta page access.
147-
mmaplock sync.RWMutex // Protects mmap access during remapping.
148-
statlock sync.RWMutex // Protects stats access.
111+
rwlock sync.Mutex // Allows only one writer at a time.
112+
metalock sync.Mutex // Protects meta page access.
149113

150-
ops struct {
151-
writeAt func(b []byte, off int64) (n int, err error)
152-
}
114+
// When enabled, the database will perform a Check() after every commit.
115+
// A panic is issued if the database is in an inconsistent state. This
116+
// flag has a large performance impact so it should only be used for
117+
// debugging purposes.
118+
StrictMode bool
119+
120+
// Setting the NoSync flag will cause the database to skip fsync()
121+
// calls after each commit. This can be useful when bulk loading data
122+
// into a database and you can restart the bulk load in the event of
123+
// a system failure or database corruption. Do not set this flag for
124+
// normal use.
125+
//
126+
// If the package global IgnoreNoSync constant is true, this value is
127+
// ignored. See the comment on that constant for more details.
128+
//
129+
// THIS IS UNSAFE. PLEASE USE WITH CAUTION.
130+
NoSync bool
131+
132+
// When true, skips syncing freelist to disk. This improves the database
133+
// write performance under normal operation, but requires a full database
134+
// re-sync during recovery.
135+
NoFreelistSync bool
136+
137+
// When true, skips the truncate call when growing the database.
138+
// Setting this to true is only safe on non-ext3/ext4 systems.
139+
// Skipping truncation avoids preallocation of hard drive space and
140+
// bypasses a truncate() and fsync() syscall on remapping.
141+
//
142+
// https://github.com/boltdb/bolt/issues/284
143+
NoGrowSync bool
144+
145+
// When `true`, bbolt will always load the free pages when opening the DB.
146+
// When opening db in write mode, this flag will always automatically
147+
// set to `true`.
148+
PreLoadFreelist bool
149+
150+
// Mlock locks database file in memory when set to true.
151+
// It prevents major page faults, however used memory can't be reclaimed.
152+
//
153+
// Supported only on Unix via mlock/munlock syscalls.
154+
Mlock bool
155+
156+
opened bool
153157

154158
// Read only mode.
155159
// When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately.
@@ -1016,8 +1020,8 @@ type call struct {
10161020
type batch struct {
10171021
db *DB
10181022
timer *time.Timer
1019-
start sync.Once
10201023
calls []call
1024+
start sync.Once
10211025
}
10221026

10231027
// trigger runs the batch if it hasn't already been run.
@@ -1284,21 +1288,13 @@ func (db *DB) freepages() []common.Pgid {
12841288

12851289
// Options represents the options that can be set when opening a database.
12861290
type Options struct {
1287-
// Timeout is the amount of time to wait to obtain a file lock.
1288-
// When set to zero it will wait indefinitely.
1289-
Timeout time.Duration
1290-
1291-
// Sets the DB.NoGrowSync flag before memory mapping the file.
1292-
NoGrowSync bool
12931291

1294-
// Do not sync freelist to disk. This improves the database write performance
1295-
// under normal operation, but requires a full database re-sync during recovery.
1296-
NoFreelistSync bool
1292+
// Logger is the logger used for bbolt.
1293+
Logger Logger
12971294

1298-
// PreLoadFreelist sets whether to load the free pages when opening
1299-
// the db file. Note when opening db in write mode, bbolt will always
1300-
// load the free pages.
1301-
PreLoadFreelist bool
1295+
// OpenFile is used to open files. It defaults to os.OpenFile. This option
1296+
// is useful for writing hermetic tests.
1297+
OpenFile func(string, int, os.FileMode) (*os.File, error)
13021298

13031299
// FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
13041300
// dramatic performance degradation if database is large and fragmentation in freelist is common.
@@ -1307,9 +1303,9 @@ type Options struct {
13071303
// The default type is array
13081304
FreelistType FreelistType
13091305

1310-
// Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
1311-
// grab a shared lock (UNIX).
1312-
ReadOnly bool
1306+
// Timeout is the amount of time to wait to obtain a file lock.
1307+
// When set to zero it will wait indefinitely.
1308+
Timeout time.Duration
13131309

13141310
// Sets the DB.MmapFlags flag before memory mapping the file.
13151311
MmapFlags int
@@ -1327,22 +1323,31 @@ type Options struct {
13271323
// PageSize overrides the default OS page size.
13281324
PageSize int
13291325

1326+
// Sets the DB.NoGrowSync flag before memory mapping the file.
1327+
NoGrowSync bool
1328+
1329+
// Do not sync freelist to disk. This improves the database write performance
1330+
// under normal operation, but requires a full database re-sync during recovery.
1331+
NoFreelistSync bool
1332+
1333+
// PreLoadFreelist sets whether to load the free pages when opening
1334+
// the db file. Note when opening db in write mode, bbolt will always
1335+
// load the free pages.
1336+
PreLoadFreelist bool
1337+
1338+
// Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
1339+
// grab a shared lock (UNIX).
1340+
ReadOnly bool
1341+
13301342
// NoSync sets the initial value of DB.NoSync. Normally this can just be
13311343
// set directly on the DB itself when returned from Open(), but this option
13321344
// is useful in APIs which expose Options but not the underlying DB.
13331345
NoSync bool
13341346

1335-
// OpenFile is used to open files. It defaults to os.OpenFile. This option
1336-
// is useful for writing hermetic tests.
1337-
OpenFile func(string, int, os.FileMode) (*os.File, error)
1338-
13391347
// Mlock locks database file in memory when set to true.
13401348
// It prevents potential page faults, however
13411349
// used memory can't be reclaimed. (UNIX only)
13421350
Mlock bool
1343-
1344-
// Logger is the logger used for bbolt.
1345-
Logger Logger
13461351
}
13471352

13481353
func (o *Options) String() string {

freelist.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ type pidSet map[common.Pgid]struct{}
2222
// freelist represents a list of all pages that are available for allocation.
2323
// It also tracks pages that have been freed but are still in use by open transactions.
2424
type freelist struct {
25-
freelistType FreelistType // freelist type
26-
ids []common.Pgid // all free and available free page ids.
2725
allocs map[common.Pgid]common.Txid // mapping of Txid that allocated a pgid.
2826
pending map[common.Txid]*txPending // mapping of soon-to-be free page ids by tx.
2927
cache map[common.Pgid]struct{} // fast lookup of all free and pending page ids.
3028
freemaps map[uint64]pidSet // key is the size of continuous pages(span), value is a set which contains the starting pgids of same size
3129
forwardMap map[common.Pgid]uint64 // key is start pgid, value is its span size
3230
backwardMap map[common.Pgid]uint64 // key is end pgid, value is its span size
33-
freePagesCount uint64 // count of free pages(hashmap version)
3431
allocate func(txid common.Txid, n int) common.Pgid // the freelist allocate func
3532
free_count func() int // the function which gives you free page number
3633
mergeSpans func(ids common.Pgids) // the mergeSpan func
3734
getFreePageIDs func() []common.Pgid // get free pgids func
3835
readIDs func(pgids []common.Pgid) // readIDs func reads list of pages and init the freelist
36+
freelistType FreelistType // freelist type
37+
ids []common.Pgid // all free and available free page ids.
38+
freePagesCount uint64 // count of free pages(hashmap version)
3939
}
4040

4141
// newFreelist returns an empty, initialized freelist.

internal/btesting/btesting.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ const (
2626

2727
// DB is a test wrapper for bolt.DB.
2828
type DB struct {
29+
t testing.TB
2930
*bolt.DB
30-
f string
3131
o *bolt.Options
32-
t testing.TB
32+
f string
3333
}
3434

3535
// MustCreateDB returns a new, open DB at a temporary location.

internal/common/inode.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import "unsafe"
66
// It can be used to point to elements in a page or point
77
// to an element which hasn't been added to a page yet.
88
type Inode struct {
9-
flags uint32
10-
pgid Pgid
119
key []byte
1210
value []byte
11+
pgid Pgid
12+
flags uint32
1313
}
1414

1515
type Inodes []Inode

internal/common/page.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,8 @@ func (n *leafPageElement) Bucket() *InBucket {
322322

323323
// PageInfo represents human readable information about a page.
324324
type PageInfo struct {
325-
ID int
326325
Type string
326+
ID int
327327
Count int
328328
OverflowCount int
329329
}

node.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import (
1111
// node represents an in-memory, deserialized page.
1212
type node struct {
1313
bucket *Bucket
14-
isLeaf bool
15-
unbalanced bool
16-
spilled bool
17-
key []byte
18-
pgid common.Pgid
1914
parent *node
15+
key []byte
2016
children nodes
2117
inodes common.Inodes
18+
pgid common.Pgid
19+
isLeaf bool
20+
unbalanced bool
21+
spilled bool
2222
}
2323

2424
// root returns the top-level node this node is attached to.

0 commit comments

Comments
 (0)