Skip to content

Commit 4810e8f

Browse files
AskAlexSharovalex
andauthored
p2p/nodedb: bench sync thresholds (#17405)
benchmarks are unreliable if run in multi-cores (because even 1 core overloading disk write io). So: , must use `-cpu=1`: ``` go test -bench=BenchmarkNodeDBGeometry/1mb_2sec -run=BenchmarkNodeDBGeometry -cpu=1 -count=10 -benchtime=5s ./p2p/enode goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/p2p/enode cpu: AMD EPYC 4344P 8-Core Processor BenchmarkNodeDBGeometry/1mb_2sec 304875 24948 ns/op 2.000 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 271047 27810 ns/op 3.000 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 246031 29828 ns/op 6.000 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 230364 31389 ns/op 9.000 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 205081 34422 ns/op 11.00 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 199292 35899 ns/op 13.00 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 189828 40628 ns/op 20.00 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 148378 47022 ns/op 17.00 ms_worst BenchmarkNodeDBGeometry/1mb_2sec 141898 48844 ns/op 18.00 ms_worst PASS ``` ``` go test -bench=BenchmarkNodeDBGeometry/5mb_2sec -run=BenchmarkNodeDBGeometry -cpu=1 -count=10 -benchtime=5s ./p2p/enode goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/p2p/enode cpu: AMD EPYC 4344P 8-Core Processor BenchmarkNodeDBGeometry/5mb_2sec 267589 30181 ns/op 3.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 252652 31581 ns/op 5.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 222480 34548 ns/op 8.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 203396 37386 ns/op 9.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 193489 39445 ns/op 12.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 177519 40932 ns/op 11.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 170472 42475 ns/op 13.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 169920 43283 ns/op 15.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 168820 42521 ns/op 14.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 171238 43919 ns/op 15.00 ms_worst ``` ``` go test -bench=BenchmarkNodeDBGeometry/5mb_2sec -run=BenchmarkNodeDBGeometry -cpu=1 -count=10 -benchtime=5s ./p2p/enode goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/p2p/enode cpu: AMD EPYC 4344P 8-Core Processor BenchmarkNodeDBGeometry/5mb_2sec 271959 29516 ns/op 3.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 268170 30549 ns/op 5.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 227325 34291 ns/op 7.000 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 202426 37019 ns/op 10.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 192224 39110 ns/op 11.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 181965 40802 ns/op 13.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 171835 42273 ns/op 14.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 164223 42940 ns/op 15.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 168981 42261 ns/op 14.00 ms_worst BenchmarkNodeDBGeometry/5mb_2sec 167252 43589 ns/op 15.00 ms_worst ``` ``` go test -bench=BenchmarkNodeDBGeometry/10mb_2sec -run=BenchmarkNodeDBGeometry -cpu=1 -count=10 -benchtime=5s ./p2p/enode goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/p2p/enode cpu: AMD EPYC 4344P 8-Core Processor BenchmarkNodeDBGeometry/10mb_2sec 241651 31061 ns/op 4.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 229740 32291 ns/op 5.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 211956 33151 ns/op 7.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 207318 34564 ns/op 8.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 190208 36950 ns/op 8.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 181152 38898 ns/op 9.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 171712 40510 ns/op 9.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 167190 41969 ns/op 10.00 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 164137 40918 ns/op 9.000 ms_worst BenchmarkNodeDBGeometry/10mb_2sec 166485 41738 ns/op 10.00 ms_worst ``` ``` go test -bench=BenchmarkNodeDBGeometry/20mb_2sec -run=BenchmarkNodeDBGeometry -cpu=1 -count=10 -benchtime=5s ./p2p/enode goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/p2p/enode cpu: AMD EPYC 4344P 8-Core Processor BenchmarkNodeDBGeometry/20mb_2sec 241070 31248 ns/op 8.000 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 201418 36015 ns/op 11.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 182701 39571 ns/op 11.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 166308 43206 ns/op 14.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 154442 46006 ns/op 16.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 146713 47762 ns/op 16.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 138229 48429 ns/op 18.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 126934 49735 ns/op 20.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 122917 49225 ns/op 21.00 ms_worst BenchmarkNodeDBGeometry/20mb_2sec 131707 48877 ns/op 19.00 ms_worst ``` Also PageSize 16kb -> 4kb: improving 30% throughput --------- Co-authored-by: alex <[email protected]>
1 parent f4cc8ca commit 4810e8f

File tree

9 files changed

+155
-160
lines changed

9 files changed

+155
-160
lines changed

db/kv/kv_interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ type RoDB interface {
125125

126126
// CHandle pointer to the underlying C environment handle, if applicable (e.g. *C.MDBX_env)
127127
CHandle() unsafe.Pointer
128+
Path() string
128129
}
129130

130131
type RwDB interface {

db/kv/mdbx/kv_mdbx.go

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -172,27 +172,6 @@ func (opts MdbxOpts) InMem(tb testing.TB, tmpDir string) MdbxOpts {
172172
return opts
173173
}
174174

175-
var pathDbMap = map[string]kv.RoDB{}
176-
var pathDbMapLock sync.Mutex
177-
178-
func addToPathDbMap(path string, db kv.RoDB) {
179-
pathDbMapLock.Lock()
180-
defer pathDbMapLock.Unlock()
181-
pathDbMap[path] = db
182-
}
183-
184-
func removeFromPathDbMap(path string) {
185-
pathDbMapLock.Lock()
186-
defer pathDbMapLock.Unlock()
187-
delete(pathDbMap, path)
188-
}
189-
190-
func PathDbMap() map[string]kv.RoDB {
191-
pathDbMapLock.Lock()
192-
defer pathDbMapLock.Unlock()
193-
return maps.Clone(pathDbMap)
194-
}
195-
196175
var ErrDBDoesNotExists = errors.New("can't create database - because opening in `Accede` mode. probably another (main) process can create it")
197176

198177
func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
@@ -432,7 +411,6 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) {
432411

433412
}
434413
db.path = opts.path
435-
addToPathDbMap(opts.path, db)
436414
if dbg.MdbxLockInRam() && opts.label == dbcfg.ChainDB {
437415
log.Info("[dbg] locking db in mem", "label", opts.label)
438416
if err := db.View(ctx, func(tx kv.Tx) error { return tx.(*MdbxTx).LockDBInRam() }); err != nil {
@@ -581,7 +559,6 @@ func (db *MdbxKV) Close() {
581559
db.log.Warn("failed to remove in-mem db file", "err", err)
582560
}
583561
}
584-
removeFromPathDbMap(db.path)
585562
}
586563

587564
func (db *MdbxKV) BeginRo(ctx context.Context) (txn kv.Tx, err error) {
@@ -1064,18 +1041,16 @@ func (tx *MdbxTx) Rollback() {
10641041
if tx.tx == nil {
10651042
return
10661043
}
1067-
defer func() {
1068-
tx.tx = nil
1069-
tx.db.trackTxEnd()
1070-
if tx.readOnly {
1071-
tx.db.roTxsLimiter.Release(1)
1072-
} else {
1073-
runtime.UnlockOSThread()
1074-
}
1075-
tx.db.leakDetector.Del(tx.traceID)
1076-
}()
10771044
tx.closeCursors()
10781045
tx.tx.Abort()
1046+
tx.tx = nil
1047+
tx.db.trackTxEnd()
1048+
if tx.readOnly {
1049+
tx.db.roTxsLimiter.Release(1)
1050+
} else {
1051+
runtime.UnlockOSThread()
1052+
}
1053+
tx.db.leakDetector.Del(tx.traceID)
10791054
}
10801055

10811056
func (tx *MdbxTx) SpaceDirty() (uint64, uint64, error) {

db/kv/mdbx/kv_mdbx_temporary.go

Lines changed: 0 additions & 110 deletions
This file was deleted.

db/kv/mdbx/kv_mdbx_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,17 @@ func TestDB_BatchTime(t *testing.T) {
928928
}
929929
}
930930

931+
func BenchmarkDB_BeginRO(b *testing.B) {
932+
_db := BaseCaseDBForBenchmark(b)
933+
db := _db.(*MdbxKV)
934+
935+
b.ResetTimer()
936+
for i := 1; i <= b.N; i++ {
937+
tx, _ := db.BeginRo(context.Background())
938+
tx.Rollback()
939+
}
940+
}
941+
931942
func BenchmarkDB_Get(b *testing.B) {
932943
_db := BaseCaseDBForBenchmark(b)
933944
table := "Table"

db/kv/remotedb/kv_remote.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ func NewRemote(v gointerfaces.Version, logger log.Logger, remoteKV remoteproto.K
131131
}
132132

133133
func (db *DB) PageSize() datasize.ByteSize { panic("not implemented") }
134+
func (db *DB) Path() string { panic("not implemented") }
134135
func (db *DB) ReadOnly() bool { return true }
135136
func (db *DB) AllTables() kv.TableCfg { return db.buckets }
136137

diagnostics/db.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"github.com/urfave/cli/v2"
2929

3030
"github.com/erigontech/erigon/db/kv"
31-
"github.com/erigontech/erigon/db/kv/mdbx"
3231
"github.com/erigontech/erigon/node/paths"
3332
)
3433

@@ -136,7 +135,8 @@ func SetupDbAccess(ctx *cli.Context, metricsMux *http.ServeMux) {
136135

137136
func writeDbList(w http.ResponseWriter, dataDir string) {
138137
w.Header().Set("Content-Type", "application/json")
139-
m := mdbx.PathDbMap()
138+
//m := mdbx.PathDbMap()
139+
m := map[string]kv.RoDB{}
140140
dbs := make([]string, 0, len(m))
141141
for path := range m {
142142
dbs = append(dbs, strings.ReplaceAll(strings.TrimPrefix(path, dataDir)[1:], "\\", "/"))
@@ -146,7 +146,8 @@ func writeDbList(w http.ResponseWriter, dataDir string) {
146146
}
147147

148148
func writeDbTables(w http.ResponseWriter, r *http.Request, dataDir string, dbname string) {
149-
m := mdbx.PathDbMap()
149+
//m := mdbx.PathDbMap()
150+
m := map[string]kv.RoDB{}
150151
db, ok := m[filepath.Join(dataDir, dbname)]
151152
if !ok {
152153
http.Error(w, fmt.Sprintf(`"%s" is not in the list of allowed dbs`, dbname), http.StatusNotFound)
@@ -199,7 +200,8 @@ func writeDbTables(w http.ResponseWriter, r *http.Request, dataDir string, dbnam
199200
}
200201

201202
func writeDbRead(w http.ResponseWriter, r *http.Request, dataDir string, dbname string, table string, key []byte, offset int64, limit int64) {
202-
m := mdbx.PathDbMap()
203+
//m := mdbx.PathDbMap()
204+
m := map[string]kv.RoDB{}
203205
db, ok := m[filepath.Join(dataDir, dbname)]
204206
if !ok {
205207
fmt.Fprintf(w, "ERROR: path %s is not in the list of allowed paths", dbname)

diagnostics/mem/common.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"github.com/erigontech/erigon/common"
2929
"github.com/erigontech/erigon/common/dbg"
3030
"github.com/erigontech/erigon/common/log/v3"
31-
"github.com/erigontech/erigon/diagnostics/diaglib"
3231
)
3332

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

88-
diaglib.Send(diaglib.MemoryStats{
89-
Alloc: m.Alloc,
90-
Sys: m.Sys,
91-
OtherFields: v.Fields(),
92-
Timestamp: time.Now(),
93-
})
94-
9587
logger.Info("[mem] memory stats", l...)
9688
UpdatePrometheusVirtualMemStats(vm)
9789
}

p2p/enode/nodedb.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,13 @@ const (
6161
// Use localItemKey to create those keys.
6262
dbLocalSeq = "seq"
6363
)
64-
6564
const (
6665
dbNodeExpiration = 24 * time.Hour // Time after which an unseen node should be dropped.
6766
dbCleanupCycle = time.Hour // Time period for running the expiration task.
6867
dbVersion = 10
6968

70-
dbSyncBytesThreshold = 5 * datasize.MB // see BenchmarkSyncPeriodDefault
71-
dbSyncPeriod = 2 * time.Second
69+
dbSyncBytesThreshold = 5 * datasize.MB // see BenchmarkNodeDBGeometry
70+
dbSyncPeriod = 2 * time.Second // see BenchmarkNodeDBGeometry
7271
)
7372

7473
var (
@@ -108,6 +107,7 @@ func newMemoryDB(ctx context.Context, logger log.Logger, tmpDir string) (*DB, er
108107
db, err := mdbx.New(dbcfg.SentryDB, logger).
109108
InMem(nil, tmpDir).
110109
WithTableCfg(bucketsConfig).
110+
PageSize(4 * datasize.KB).
111111
MapSize(1 * datasize.GB).
112112
Open(ctx)
113113
if err != nil {
@@ -123,12 +123,14 @@ func newMemoryDB(ctx context.Context, logger log.Logger, tmpDir string) (*DB, er
123123
// newPersistentDB creates/opens a persistent node database,
124124
// also flushing its contents in case of a version mismatch.
125125
func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB, error) {
126+
// see `BenchmarkNodeDBGeometry`
126127
db, err := mdbx.New(dbcfg.SentryDB, logger).
127128
Path(path).
128129
WithTableCfg(bucketsConfig).
130+
PageSize(4 * datasize.KB).
129131
MapSize(8 * datasize.GB).
130-
GrowthStep(16 * datasize.MB).
131-
Flags(func(f uint) uint { return f&^mdbx1.Durable | mdbx1.SafeNoSync }).
132+
GrowthStep(2 * datasize.MB).
133+
Flags(func(f uint) uint { return f&^mdbx1.Durable | mdbx1.SafeNoSync | mdbx1.WriteMap }).
132134
SyncBytes(dbSyncBytesThreshold).
133135
SyncPeriod(dbSyncPeriod).
134136
DirtySpace(uint64(32 * datasize.MB)).

0 commit comments

Comments
 (0)