Skip to content

Commit 97dddf5

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 3fd94a4 commit 97dddf5

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
@@ -370,10 +370,10 @@ func newPageItemCommand(m *Main) *pageItemCommand {
370370
}
371371

372372
type pageItemOptions struct {
373+
format string
373374
help bool
374375
keyOnly bool
375376
valueOnly bool
376-
format string
377377
}
378378

379379
// Run executes the command.
@@ -1617,8 +1617,8 @@ func (r *BenchResults) OpsPerSecond() int {
16171617
}
16181618

16191619
type PageError struct {
1620-
ID int
16211620
Err error
1621+
ID int
16221622
}
16231623

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

db.go

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

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

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

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

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

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

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

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

136-
freelist *freelist
137106
freelistLoad sync.Once
138107

139-
pagePool sync.Pool
140-
141108
batchMu sync.Mutex
142-
batch *batch
143109

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

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

153157
// Read only mode.
154158
// When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately.
@@ -995,8 +999,8 @@ type call struct {
995999
type batch struct {
9961000
db *DB
9971001
timer *time.Timer
998-
start sync.Once
9991002
calls []call
1003+
start sync.Once
10001004
}
10011005

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

12641268
// Options represents the options that can be set when opening a database.
12651269
type Options struct {
1266-
// Timeout is the amount of time to wait to obtain a file lock.
1267-
// When set to zero it will wait indefinitely.
1268-
Timeout time.Duration
1269-
1270-
// Sets the DB.NoGrowSync flag before memory mapping the file.
1271-
NoGrowSync bool
12721270

1273-
// Do not sync freelist to disk. This improves the database write performance
1274-
// under normal operation, but requires a full database re-sync during recovery.
1275-
NoFreelistSync bool
1271+
// Logger is the logger used for bbolt.
1272+
Logger Logger
12761273

1277-
// PreLoadFreelist sets whether to load the free pages when opening
1278-
// the db file. Note when opening db in write mode, bbolt will always
1279-
// load the free pages.
1280-
PreLoadFreelist bool
1274+
// OpenFile is used to open files. It defaults to os.OpenFile. This option
1275+
// is useful for writing hermetic tests.
1276+
OpenFile func(string, int, os.FileMode) (*os.File, error)
12811277

12821278
// FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
12831279
// dramatic performance degradation if database is large and fragmentation in freelist is common.
@@ -1286,9 +1282,9 @@ type Options struct {
12861282
// The default type is array
12871283
FreelistType FreelistType
12881284

1289-
// Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
1290-
// grab a shared lock (UNIX).
1291-
ReadOnly bool
1285+
// Timeout is the amount of time to wait to obtain a file lock.
1286+
// When set to zero it will wait indefinitely.
1287+
Timeout time.Duration
12921288

12931289
// Sets the DB.MmapFlags flag before memory mapping the file.
12941290
MmapFlags int
@@ -1306,22 +1302,31 @@ type Options struct {
13061302
// PageSize overrides the default OS page size.
13071303
PageSize int
13081304

1305+
// Sets the DB.NoGrowSync flag before memory mapping the file.
1306+
NoGrowSync bool
1307+
1308+
// Do not sync freelist to disk. This improves the database write performance
1309+
// under normal operation, but requires a full database re-sync during recovery.
1310+
NoFreelistSync bool
1311+
1312+
// PreLoadFreelist sets whether to load the free pages when opening
1313+
// the db file. Note when opening db in write mode, bbolt will always
1314+
// load the free pages.
1315+
PreLoadFreelist bool
1316+
1317+
// Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
1318+
// grab a shared lock (UNIX).
1319+
ReadOnly bool
1320+
13091321
// NoSync sets the initial value of DB.NoSync. Normally this can just be
13101322
// set directly on the DB itself when returned from Open(), but this option
13111323
// is useful in APIs which expose Options but not the underlying DB.
13121324
NoSync bool
13131325

1314-
// OpenFile is used to open files. It defaults to os.OpenFile. This option
1315-
// is useful for writing hermetic tests.
1316-
OpenFile func(string, int, os.FileMode) (*os.File, error)
1317-
13181326
// Mlock locks database file in memory when set to true.
13191327
// It prevents potential page faults, however
13201328
// used memory can't be reclaimed. (UNIX only)
13211329
Mlock bool
1322-
1323-
// Logger is the logger used for bbolt.
1324-
Logger Logger
13251330
}
13261331

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

freelist.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ type pidSet map[common.Pgid]struct{}
2323
// freelist represents a list of all pages that are available for allocation.
2424
// It also tracks pages that have been freed but are still in use by open transactions.
2525
type freelist struct {
26-
freelistType FreelistType // freelist type
27-
ids []common.Pgid // all free and available free page ids.
28-
readonlyTXIDs []common.Txid // all readonly transaction IDs.
2926
allocs map[common.Pgid]common.Txid // mapping of Txid that allocated a pgid.
3027
pending map[common.Txid]*txPending // mapping of soon-to-be free page ids by tx.
3128
cache map[common.Pgid]struct{} // fast lookup of all free and pending page ids.
@@ -38,6 +35,9 @@ type freelist struct {
3835
mergeSpans func(ids common.Pgids) // the mergeSpan func
3936
getFreePageIDs func() []common.Pgid // get free pgids func
4037
readIDs func(pgids []common.Pgid) // readIDs func reads list of pages and init the freelist
38+
freelistType FreelistType // freelist type
39+
ids []common.Pgid // all free and available free page ids.
40+
readonlyTXIDs []common.Txid // all readonly transaction IDs.
4141
}
4242

4343
// 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)