mdbx: dplimit - support cgroups/gomelimit, avoid using SetOptions after env.Open() (#9189)

This commit is contained in:
Alex Sharov 2024-01-11 08:06:35 +07:00 committed by GitHub
parent 641f53e9d2
commit 1ee439e6ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 50 additions and 37 deletions

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -1,3 +1,5 @@
//go:build integration
package handler
import (

View File

@ -34,8 +34,8 @@ import (
"github.com/c2h5oh/datasize"
"github.com/erigontech/mdbx-go/mdbx"
stack2 "github.com/go-stack/stack"
"github.com/ledgerwatch/erigon-lib/mmap"
"github.com/ledgerwatch/log/v3"
"github.com/pbnjay/memory"
"golang.org/x/exp/maps"
"golang.org/x/sync/semaphore"
@ -84,10 +84,6 @@ func NewMDBX(log log.Logger) MdbxOpts {
log: log,
pageSize: kv.DefaultPageSize(),
// default is (TOTAL_RAM+AVAILABLE_RAM)/42/pageSize
// but for reproducibility of benchmarks - please don't rely on Available RAM
dirtySpace: 2 * (memory.TotalMemory() / 42),
mapSize: DefaultMapSize,
growthStep: DefaultGrowthStep,
mergeThreshold: 3 * 8192,
@ -280,7 +276,7 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
return nil, err
}
if opts.flags&mdbx.Accede == 0 {
if !opts.HasFlag(mdbx.Accede) {
if err = env.SetGeometry(-1, -1, int(opts.mapSize), int(opts.growthStep), opts.shrinkThreshold, int(opts.pageSize)); err != nil {
return nil, err
}
@ -289,29 +285,6 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
}
}
err = env.Open(opts.path, opts.flags, 0664)
if err != nil {
if err != nil {
return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String())
}
}
// mdbx will not change pageSize if db already exists. means need read real value after env.open()
in, err := env.Info(nil)
if err != nil {
if err != nil {
return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String())
}
}
opts.pageSize = uint64(in.PageSize)
opts.mapSize = datasize.ByteSize(in.MapSize)
if opts.label == kv.ChainDB {
opts.log.Info("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize)
} else {
opts.log.Debug("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize)
}
// erigon using big transactions
// increase "page measured" options. need do it after env.Open() because default are depend on pageSize known only after env.Open()
if !opts.HasFlag(mdbx.Readonly) {
@ -339,17 +312,19 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
}
}
// before env.Open() we don't know real pageSize. but will be implemented soon: https://gitflic.ru/project/erthink/libmdbx/issue/15
// but we want call all `SetOption` before env.Open(), because:
// - after they will require rwtx-lock, which is not acceptable in ACCEDEE mode.
pageSize := opts.pageSize
if pageSize == 0 {
pageSize = kv.DefaultPageSize()
}
var dirtySpace uint64
if opts.dirtySpace > 0 {
dirtySpace = opts.dirtySpace
} else {
// the default value is based on the RAM amount
dirtyPagesLimit, err := env.GetOption(mdbx.OptTxnDpLimit)
if err != nil {
return nil, err
}
dirtySpace = dirtyPagesLimit * opts.pageSize
dirtySpace = mmap.TotalMemory() / 42 // it's default of mdbx, but our package also supports cgroups and GOMEMLIMIT
// clamp to max size
const dirtySpaceMaxChainDB = uint64(2 * datasize.GB)
const dirtySpaceMaxDefault = uint64(256 * datasize.MB)
@ -360,7 +335,8 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
dirtySpace = dirtySpaceMaxDefault
}
}
if err = env.SetOption(mdbx.OptTxnDpLimit, dirtySpace/opts.pageSize); err != nil {
//can't use real pagesize here - it will be known only after env.Open()
if err = env.SetOption(mdbx.OptTxnDpLimit, dirtySpace/pageSize); err != nil {
return nil, err
}
@ -371,6 +347,25 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
}
}
err = env.Open(opts.path, opts.flags, 0664)
if err != nil {
return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String())
}
// mdbx will not change pageSize if db already exists. means need read real value after env.open()
in, err := env.Info(nil)
if err != nil {
return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String())
}
opts.pageSize = uint64(in.PageSize)
opts.mapSize = datasize.ByteSize(in.MapSize)
if opts.label == kv.ChainDB {
opts.log.Info("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize)
} else {
opts.log.Debug("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize)
}
dirtyPagesLimit, err := env.GetOption(mdbx.OptTxnDpLimit)
if err != nil {
return nil, err