Skip to content
Open
21 changes: 12 additions & 9 deletions db/kv/mdbx/kv_mdbx.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ type MdbxOpts struct {
log log.Logger
bucketsCfg TableCfgFunc
path string
syncPeriod time.Duration // to be used only in combination with SafeNoSync flag. The dirty data will automatically be flushed to disk periodically in the background.
syncBytes *uint // to be used only in combination with SafeNoSync flag. The dirty data will be flushed to disk when this threshold is reached.
syncPeriod time.Duration // to be used only in combination with SafeNoSync flag. The dirty data will automatically be flushed to disk periodically in the background.
syncBytes *datasize.ByteSize // to be used only in combination with SafeNoSync flag. The dirty data will be flushed to disk when this threshold is reached.
mapSize datasize.ByteSize
growthStep datasize.ByteSize
shrinkThreshold int
Expand Down Expand Up @@ -123,12 +123,15 @@ func (opts MdbxOpts) PageSize(v datasize.ByteSize) MdbxOpts { opts.pageSiz
func (opts MdbxOpts) GrowthStep(v datasize.ByteSize) MdbxOpts { opts.growthStep = v; return opts }
func (opts MdbxOpts) Path(path string) MdbxOpts { opts.path = path; return opts }
func (opts MdbxOpts) SyncPeriod(period time.Duration) MdbxOpts { opts.syncPeriod = period; return opts }
func (opts MdbxOpts) SyncBytes(threshold uint) MdbxOpts { opts.syncBytes = &threshold; return opts }
func (opts MdbxOpts) DBVerbosity(v kv.DBVerbosityLvl) MdbxOpts { opts.verbosity = v; return opts }
func (opts MdbxOpts) MapSize(sz datasize.ByteSize) MdbxOpts { opts.mapSize = sz; return opts }
func (opts MdbxOpts) WriteMergeThreshold(v uint64) MdbxOpts { opts.mergeThreshold = v; return opts }
func (opts MdbxOpts) WithTableCfg(f TableCfgFunc) MdbxOpts { opts.bucketsCfg = f; return opts }
func (opts MdbxOpts) WithMetrics() MdbxOpts { opts.metrics = true; return opts }
func (opts MdbxOpts) SyncBytes(threshold datasize.ByteSize) MdbxOpts {
opts.syncBytes = &threshold
return opts
}
func (opts MdbxOpts) DBVerbosity(v kv.DBVerbosityLvl) MdbxOpts { opts.verbosity = v; return opts }
func (opts MdbxOpts) MapSize(sz datasize.ByteSize) MdbxOpts { opts.mapSize = sz; return opts }
func (opts MdbxOpts) WriteMergeThreshold(v uint64) MdbxOpts { opts.mergeThreshold = v; return opts }
func (opts MdbxOpts) WithTableCfg(f TableCfgFunc) MdbxOpts { opts.bucketsCfg = f; return opts }
func (opts MdbxOpts) WithMetrics() MdbxOpts { opts.metrics = true; return opts }

// Flags
func (opts MdbxOpts) HasFlag(flag uint) bool { return opts.flags&flag != 0 }
Expand Down Expand Up @@ -355,7 +358,7 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
}

if opts.HasFlag(mdbx.SafeNoSync) && opts.syncBytes != nil {
if err = env.SetSyncBytes(*opts.syncBytes); err != nil {
if err = env.SetSyncBytes(uint(opts.syncBytes.Bytes())); err != nil {
env.Close()
return nil, err
}
Expand Down
90 changes: 90 additions & 0 deletions db/kv/mdbx/kv_mdbx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"context"
"encoding/binary"
"errors"
"fmt"
"math/rand"
"os"
"sync/atomic"
"testing"
"time"
Expand All @@ -37,6 +39,94 @@ import (
"github.com/erigontech/erigon/db/kv/stream"
)

// BenchmarkSyncPeriodDefault for `dbSyncBytesThreshold` constant
// - run: go test -bench=BenchmarkSyncPeriodDefault -run=BenchmarkSyncPeriodDefault -count=2 -benchtime=15s ./db/kv/mdbx
// - -benchtime can't be smaller than SyncPeriod
func BenchmarkSyncPeriodDefault(b *testing.B) {
keys, vals := make([][]byte, 1_000_000), make([][]byte, 1_000_000)
for i := range keys {
keys[i] = []byte(fmt.Sprintf("key %d", i))
vals[i] = []byte(fmt.Sprintf("val %d", i))
}
cfg := New(dbcfg.ChainDB, log.New()).
MapSize(18 * datasize.GB).
GrowthStep(1 * datasize.MB).
Flags(func(f uint) uint { return f&^mdbxgo.Durable | mdbxgo.SafeNoSync }).
SyncBytes(20 * datasize.MB).
SyncPeriod(2 * time.Second).
DirtySpace(uint64(32 * datasize.MB)).
PageSize(16 * datasize.KB)

doBench := func(b *testing.B, db kv.RwDB) {
//b.ReportAllocs()
b.ResetTimer()
var worst time.Duration
var i int
for b.Loop() {
i++
tx, _ := db.BeginRw(context.Background())
_ = tx.Put(kv.Headers, keys[i%len(keys)], vals[i%len(vals)])

t := time.Now()
_ = tx.Commit()
worst = max(worst, time.Since(t))
}
b.ReportMetric(float64(worst.Milliseconds()), "ms_worst")
db.Close()
os.RemoveAll(db.(*MdbxKV).path)
}

b.Run("20kb", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(20 * datasize.KB).MustOpen()
defer db.Close()
doBench(b, db)
})
b.Run("200kb", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(200 * datasize.KB).MustOpen()
defer db.Close()
doBench(b, db)
})
b.Run("2mb", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(2 * datasize.MB).MustOpen()
defer db.Close()
doBench(b, db)
})

b.Run("10mb 1sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(10 * datasize.MB).SyncPeriod(1 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})

b.Run("10mb 2sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(10 * datasize.MB).SyncPeriod(2 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})
b.Run("10mb 5sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(10 * datasize.MB).SyncPeriod(5 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})

b.Run("20mb 1sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(20 * datasize.MB).SyncPeriod(1 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})

b.Run("20mb 2sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(20 * datasize.MB).SyncPeriod(2 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})
b.Run("20mb 5sec", func(b *testing.B) {
db := cfg.Path(b.TempDir()).SyncBytes(20 * datasize.MB).SyncPeriod(5 * time.Second).MustOpen()
defer db.Close()
doBench(b, db)
})
}

func BaseCaseDB(t *testing.T) kv.RwDB {
t.Helper()
path := t.TempDir()
Expand Down
8 changes: 0 additions & 8 deletions diagnostics/mem/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/erigontech/erigon/common"
"github.com/erigontech/erigon/common/dbg"
"github.com/erigontech/erigon/common/log/v3"
"github.com/erigontech/erigon/diagnostics/diaglib"
)

var ErrorUnsupportedPlatform = errors.New("unsupported platform")
Expand Down Expand Up @@ -85,13 +84,6 @@ func LogMemStats(ctx context.Context, logger log.Logger) {
l := v.Fields()
l = append(l, "alloc", common.ByteCount(m.Alloc), "sys", common.ByteCount(m.Sys))

diaglib.Send(diaglib.MemoryStats{
Alloc: m.Alloc,
Sys: m.Sys,
OtherFields: v.Fields(),
Timestamp: time.Now(),
})

logger.Info("[mem] memory stats", l...)
UpdatePrometheusVirtualMemStats(vm)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ replace github.com/holiman/bloomfilter/v2 => github.com/AskAlexSharov/bloomfilte
require (
github.com/erigontech/erigon-snapshot v1.3.1-0.20250718024755-5b6d5407844d
github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116
github.com/erigontech/mdbx-go v0.39.9
github.com/erigontech/mdbx-go v0.39.10
github.com/erigontech/secp256k1 v1.2.0
github.com/erigontech/silkworm-go v0.24.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ github.com/erigontech/erigon-snapshot v1.3.1-0.20250718024755-5b6d5407844d h1:8E
github.com/erigontech/erigon-snapshot v1.3.1-0.20250718024755-5b6d5407844d/go.mod h1:ooHlCl+eEYzebiPu+FP6Q6SpPUeMADn8Jxabv3IKb9M=
github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116 h1:KCFa2uXEfZoBjV4buzjWmCmoqVLXiGCq0ZmQ2OjeRvQ=
github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116/go.mod h1:8vQ+VjvLu2gkPs8EwdPrOTAAo++WuLuBi54N7NuAF0I=
github.com/erigontech/mdbx-go v0.39.9 h1:lu3iycXllChqnxn9oqfzSdfoHRahp3R2ClxmjMTtwDQ=
github.com/erigontech/mdbx-go v0.39.9/go.mod h1:tHUS492F5YZvccRqatNdpTDQAaN+Vv4HRARYq89KqeY=
github.com/erigontech/mdbx-go v0.39.10 h1:eZnSDySAl1Kp7MvcsAFmfa1nKiGvNNRkezyrsmUKrB4=
github.com/erigontech/mdbx-go v0.39.10/go.mod h1:tHUS492F5YZvccRqatNdpTDQAaN+Vv4HRARYq89KqeY=
github.com/erigontech/secp256k1 v1.2.0 h1:Q/HCBMdYYT0sh1xPZ9ZYEnU30oNyb/vt715cJhj7n7A=
github.com/erigontech/secp256k1 v1.2.0/go.mod h1:GokhPepsMB+EYDs7I5JZCprxHW6+yfOcJKaKtoZ+Fls=
github.com/erigontech/silkworm-go v0.24.0 h1:fFe74CjQM5LI7ouMYjmqfFaqIFzQTpMrt+ls+a5PxpE=
Expand Down
14 changes: 8 additions & 6 deletions p2p/enode/nodedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ const (
)

const (
dbNodeExpiration = 24 * time.Hour // Time after which an unseen node should be dropped.
dbCleanupCycle = time.Hour // Time period for running the expiration task.
dbVersion = 10
dbSyncBytesThreshold = 20_000 // if we have about 20kb of dirty data , then flush to disk
dbNodeExpiration = 24 * time.Hour // Time after which an unseen node should be dropped.
dbCleanupCycle = time.Hour // Time period for running the expiration task.
dbVersion = 10

dbSyncBytesThreshold = 10 * datasize.MB // see `BenchmarkSyncPeriodDefault`
dbSyncPeriod = 2 * time.Second // see `BenchmarkSyncPeriodDefault`
)

var (
Expand Down Expand Up @@ -125,10 +127,10 @@ func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB,
Path(path).
WithTableCfg(bucketsConfig).
MapSize(8 * datasize.GB).
GrowthStep(16 * datasize.MB).
GrowthStep(2 * datasize.MB).
Flags(func(f uint) uint { return f&^mdbx1.Durable | mdbx1.SafeNoSync }).
SyncBytes(dbSyncBytesThreshold).
SyncPeriod(2 * time.Second).
SyncPeriod(dbSyncPeriod).
DirtySpace(uint64(32 * datasize.MB)).
// WithMetrics().
Open(ctx)
Expand Down
Loading