Use MAP_POPULATE for our bbolt mmaps (#13573)
* Use MAP_POPULATE for our bbolt mmaps, assuming the files fit in memory. This should improve startup times when freelist sync is disabled.
This commit is contained in:
parent
9956c051d2
commit
4ee4374b3e
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
storage/raft: On linux, use map_populate for bolt files to improve startup time.
|
||||||
|
```
|
|
@ -32,7 +32,7 @@ func Test_BoltOptions(t *testing.T) {
|
||||||
os.Setenv(key, tc.env)
|
os.Setenv(key, tc.env)
|
||||||
}
|
}
|
||||||
|
|
||||||
o := boltOptions()
|
o := boltOptions("")
|
||||||
|
|
||||||
if o.InitialMmapSize != tc.expectedSize {
|
if o.InitialMmapSize != tc.expectedSize {
|
||||||
t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize)
|
t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize)
|
||||||
|
|
|
@ -32,7 +32,7 @@ func Test_BoltOptions(t *testing.T) {
|
||||||
os.Setenv(key, tc.env)
|
os.Setenv(key, tc.env)
|
||||||
}
|
}
|
||||||
|
|
||||||
o := boltOptions()
|
o := boltOptions("")
|
||||||
|
|
||||||
if o.InitialMmapSize != tc.expectedSize {
|
if o.InitialMmapSize != tc.expectedSize {
|
||||||
t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize)
|
t.Errorf("expected InitialMmapSize to be %d but it was %d", tc.expectedSize, o.InitialMmapSize)
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package raft
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/mem"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
getMmapFlags = getMmapFlagsLinux
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
|
@ -168,7 +168,7 @@ func (f *FSM) openDBFile(dbPath string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := boltOptions()
|
opts := boltOptions(dbPath)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
boltDB, err := bolt.Open(dbPath, 0o600, opts)
|
boltDB, err := bolt.Open(dbPath, 0o600, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -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.
|
// EnvVaultRaftPath is used to fetch the path where Raft data is stored from the environment.
|
||||||
const EnvVaultRaftPath = "VAULT_RAFT_PATH"
|
const EnvVaultRaftPath = "VAULT_RAFT_PATH"
|
||||||
|
|
||||||
|
var getMmapFlags = func(string) int { return 0 }
|
||||||
|
|
||||||
// Verify RaftBackend satisfies the correct interfaces
|
// Verify RaftBackend satisfies the correct interfaces
|
||||||
var (
|
var (
|
||||||
_ physical.Backend = (*RaftBackend)(nil)
|
_ 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.
|
// Create the backend raft store for logs and stable storage.
|
||||||
opts := boltOptions()
|
dbPath := filepath.Join(path, "raft.db")
|
||||||
|
opts := boltOptions(dbPath)
|
||||||
raftOptions := raftboltdb.Options{
|
raftOptions := raftboltdb.Options{
|
||||||
Path: filepath.Join(path, "raft.db"),
|
Path: dbPath,
|
||||||
BoltOptions: opts,
|
BoltOptions: opts,
|
||||||
}
|
}
|
||||||
store, err := raftboltdb.New(raftOptions)
|
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
|
// boltOptions returns a bolt.Options struct, suitable for passing to
|
||||||
// bolt.Open(), pre-configured with all of our preferred defaults.
|
// bolt.Open(), pre-configured with all of our preferred defaults.
|
||||||
func boltOptions() *bolt.Options {
|
func boltOptions(path string) *bolt.Options {
|
||||||
o := &bolt.Options{
|
o := &bolt.Options{
|
||||||
Timeout: 1 * time.Second,
|
Timeout: 1 * time.Second,
|
||||||
FreelistType: bolt.FreelistMapType,
|
FreelistType: bolt.FreelistMapType,
|
||||||
NoFreelistSync: true,
|
NoFreelistSync: true,
|
||||||
|
MmapFlags: getMmapFlags(path),
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("VAULT_RAFT_FREELIST_TYPE") == "array" {
|
if os.Getenv("VAULT_RAFT_FREELIST_TYPE") == "array" {
|
||||||
|
|
Loading…
Reference in New Issue