Skip to content

Commit

Permalink
walletdb/bdb: attempt to set initial memory map size when opening
Browse files Browse the repository at this point in the history
In this commit, we start to set the initial memory map size when opening
the database. This helps with bulk insertions or migrations of the
database, as if we set this to a larger value, then bbolt needs to remap
less often. Remapping can be memory intensive as it needs to copy over
the entire existing database.

For 32-bit systems, we take care to clamp this value to ensure we don't
exceed the largest addressable memory on such systems.
  • Loading branch information
Roasbeef committed May 4, 2020
1 parent eb083ea commit d4264e1
Showing 1 changed file with 36 additions and 0 deletions.
36 changes: 36 additions & 0 deletions walletdb/bdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,18 @@ func fileExists(name string) bool {
return true
}

const (
// is64Bit tells us if we're running on a 64-bit system or not. If uintptr is
// 32 bits, then its complement will be 0xffffffff rather than
// 0xffffffffffffffff. The complement of uint64(0) will always be
// 0xffffffffffffffff.
is64Bit = uint64(^uintptr(0)) == ^uint64(0)

// max32BitMapSize is the largest mmap size we can support on 32-bit
// systems. (2^31)-1 == 0x7FFFFFFF.
max32BitMapSize = 0x7FFFFFFF
)

// openDB opens the database at the provided path. walletdb.ErrDbDoesNotExist
// is returned if the database doesn't exist and the create flag is not set.
func openDB(dbPath string, create bool, options *bbolt.Options) (walletdb.DB, error) {
Expand All @@ -375,6 +387,30 @@ func openDB(dbPath string, create bool, options *bbolt.Options) (walletdb.DB, er
// Specify bbolt freelist options to reduce heap pressure in case the
// freelist grows to be very large.
options.FreelistType = bbolt.FreelistMapType

if !create {
// The other value that we want to set is the initial memory
// map size. When bolt expands the mmap, it actually copies
// over the entire database. By setting this to a large value
// than zero, then we can avoid some of that heap pressure due
// to the copies.
dbFileInfo, err := os.Stat(dbPath)
if err != nil {
return nil, err
}

// We'll aim to set the initial memory map to 2x the size of
// the database as it exists on disk, meaning the DB size can
// double without us having to remap everything.
mmapSize := dbFileInfo.Size() * 2

// If we're on a 32-bit system, then we'll need to limit this
// value to ensure we don't run into errors down the line.
if !is64Bit {
mmapSize = max32BitMapSize
}

options.InitialMmapSize = int(mmapSize)
}

boltDB, err := bbolt.Open(dbPath, 0600, options)
Expand Down

0 comments on commit d4264e1

Please sign in to comment.