From fd4bba41a83efa9bd2d5d1dd039bb0ce17c1356c Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Wed, 5 Jan 2022 10:52:36 -0500 Subject: [PATCH 1/4] Use MAP_POPULATE for our bbolt mmaps, assuming the files fit in memory. This should improve startup times when freelist sync is disabled. --- physical/raft/bolt_linux.go | 33 +++++++++++++++++++++++++++++++++ physical/raft/fsm.go | 2 +- physical/raft/raft.go | 10 +++++++--- 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 physical/raft/bolt_linux.go diff --git a/physical/raft/bolt_linux.go b/physical/raft/bolt_linux.go new file mode 100644 index 000000000000..a38896b0c79e --- /dev/null +++ b/physical/raft/bolt_linux.go @@ -0,0 +1,33 @@ +package raft + +import ( + "context" + "os" + + "github.com/shirou/gopsutil/mem" + "golang.org/x/sys/unix" +) + +func init() { + getMmapFlags = getMmapFlagsLinux +} + +func getMmapFlagsLinux(dbPath string) int { + stat, err := os.Stat(dbPath) + if err != nil { + return 0 + } + size := stat.Size() + + v, err := mem.VirtualMemoryWithContext(context.Background()) + if err != nil { + return 0 + } + + // We won't worry about swap, since we already tell people not to use it. + if v.Total > uint64(size) { + return unix.MAP_POPULATE + } + + return 0 +} diff --git a/physical/raft/fsm.go b/physical/raft/fsm.go index 8c2e79fbde15..ab8d75a6fd2a 100644 --- a/physical/raft/fsm.go +++ b/physical/raft/fsm.go @@ -168,7 +168,7 @@ func (f *FSM) openDBFile(dbPath string) error { } } - opts := boltOptions() + opts := boltOptions(dbPath) start := time.Now() boltDB, err := bolt.Open(dbPath, 0o600, opts) if err != nil { diff --git a/physical/raft/raft.go b/physical/raft/raft.go index 52826c09c4aa..2b2de78ac76a 100644 --- a/physical/raft/raft.go +++ b/physical/raft/raft.go @@ -40,6 +40,8 @@ const EnvVaultRaftNodeID = "VAULT_RAFT_NODE_ID" // EnvVaultRaftPath is used to fetch the path where Raft data is stored from the environment. const EnvVaultRaftPath = "VAULT_RAFT_PATH" +var getMmapFlags = func(string) int { return 0 } + // Verify RaftBackend satisfies the correct interfaces var ( _ physical.Backend = (*RaftBackend)(nil) @@ -364,9 +366,10 @@ func NewRaftBackend(conf map[string]string, logger log.Logger) (physical.Backend } // Create the backend raft store for logs and stable storage. - opts := boltOptions() + dbPath := filepath.Join(path, "raft.db") + opts := boltOptions(dbPath) raftOptions := raftboltdb.Options{ - Path: filepath.Join(path, "raft.db"), + Path: dbPath, BoltOptions: opts, } store, err := raftboltdb.New(raftOptions) @@ -1649,11 +1652,12 @@ func (s sealer) Open(ctx context.Context, ct []byte) ([]byte, error) { // boltOptions returns a bolt.Options struct, suitable for passing to // bolt.Open(), pre-configured with all of our preferred defaults. -func boltOptions() *bolt.Options { +func boltOptions(path string) *bolt.Options { o := &bolt.Options{ Timeout: 1 * time.Second, FreelistType: bolt.FreelistMapType, NoFreelistSync: true, + MmapFlags: getMmapFlags(path), } if os.Getenv("VAULT_RAFT_FREELIST_TYPE") == "array" { From 33599e388d64b3337100684ecfd0d41ce500e7ee Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Wed, 5 Jan 2022 11:04:27 -0500 Subject: [PATCH 2/4] Add CL. --- changelog/13573.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/13573.txt diff --git a/changelog/13573.txt b/changelog/13573.txt new file mode 100644 index 000000000000..f9088548104c --- /dev/null +++ b/changelog/13573.txt @@ -0,0 +1,3 @@ +```release-note:bug +storage/raft: On linux, use map_populate for bolt files to improve startup time. +``` From 3277af7df39ac880a644483d5cc4bf1f86438964 Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Wed, 5 Jan 2022 12:11:05 -0500 Subject: [PATCH 3/4] Fix tests. --- physical/raft/bolt_32bit_test.go | 3 ++- physical/raft/bolt_64bit_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/physical/raft/bolt_32bit_test.go b/physical/raft/bolt_32bit_test.go index 7fceb0d50ea1..e39c8bd9c198 100644 --- a/physical/raft/bolt_32bit_test.go +++ b/physical/raft/bolt_32bit_test.go @@ -1,3 +1,4 @@ +//go:build 386 || arm // +build 386 arm package raft @@ -32,7 +33,7 @@ func Test_BoltOptions(t *testing.T) { os.Setenv(key, tc.env) } - o := boltOptions() + o := boltOptions("") if o.InitialMmapSize != tc.expectedSize { t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize) diff --git a/physical/raft/bolt_64bit_test.go b/physical/raft/bolt_64bit_test.go index 20ec4ea43f0b..f15a66c97dbf 100644 --- a/physical/raft/bolt_64bit_test.go +++ b/physical/raft/bolt_64bit_test.go @@ -1,3 +1,4 @@ +//go:build !386 && !arm // +build !386,!arm package raft @@ -32,7 +33,7 @@ func Test_BoltOptions(t *testing.T) { os.Setenv(key, tc.env) } - o := boltOptions() + o := boltOptions("") if o.InitialMmapSize != tc.expectedSize { t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize) From d4b24b8bea1ea907f84ce643bba1be30c7adec2d Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Mon, 10 Jan 2022 15:25:23 -0500 Subject: [PATCH 4/4] Add env override option for MAP_POPULATE. --- physical/raft/bolt_linux.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/physical/raft/bolt_linux.go b/physical/raft/bolt_linux.go index a38896b0c79e..03db74bc475c 100644 --- a/physical/raft/bolt_linux.go +++ b/physical/raft/bolt_linux.go @@ -13,6 +13,9 @@ func init() { } func getMmapFlagsLinux(dbPath string) int { + if os.Getenv("VAULT_RAFT_DISABLE_MAP_POPULATE") != "" { + return 0 + } stat, err := os.Stat(dbPath) if err != nil { return 0