diff --git a/Makefile b/Makefile index d66e4797f41..33baf487c54 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ DOCKER_TAG ?= erigontech/erigon:latest CGO_CFLAGS := $(shell $(GO) env CGO_CFLAGS 2>/dev/null) # don't lose default #CGO_CFLAGS += -DMDBX_FORCE_ASSERTIONS=0 # Enable MDBX's asserts by default in 'main' branch and disable in releases #CGO_CFLAGS += -DMDBX_DISABLE_VALIDATION=0 # Can disable it on CI by separated PR which will measure perf impact. -#CGO_CFLAGS += -DMDBX_ENABLE_PROFGC=0 # Disabled by default, but may be useful for performance debugging -#CGO_CFLAGS += -DMDBX_ENABLE_PGOP_STAT=0 # Disabled by default, but may be useful for performance debugging +CGO_CFLAGS += -DMDBX_ENABLE_PROFGC=1 # Disabled by default, but may be useful for performance debugging +CGO_CFLAGS += -DMDBX_ENABLE_PGOP_STAT=1 # Disabled by default, but may be useful for performance debugging #CGO_CFLAGS += -DMDBX_ENV_CHECKPID=0 # Erigon doesn't do fork() syscall diff --git a/db/kv/kv_interface.go b/db/kv/kv_interface.go index 6123b58c9f3..c6e071792c4 100644 --- a/db/kv/kv_interface.go +++ b/db/kv/kv_interface.go @@ -613,6 +613,11 @@ type DBSummaries struct { // the summaries are particular to a DB instance DbCommitTotal metrics.Summary } +type GCSummaries struct { // GC metric summaries for each DB instance + GCMaxRetainedPages metrics.Summary + GCMaxReaderLag metrics.Summary +} + // InitMDBXMGauges this only needs to be called once during startup func InitMDBXMGauges() *DBGauges { return &DBGauges{ @@ -652,8 +657,20 @@ func InitSummaries(dbLabel Label) { } } +func InitGCSummaries(dbLabel Label) { + _, ok := MDBXGCSummaries.Load(dbLabel) + if !ok { + dbName := string(dbLabel) + MDBXGCSummaries.Store(dbName, &GCSummaries{ + GCMaxRetainedPages: metrics.GetOrCreateSummaryWithLabels(`db_gc_max_retained_pages`, []string{dbLabelName}, []string{dbName}), + GCMaxReaderLag: metrics.GetOrCreateSummaryWithLabels(`db_gc_max_reader_lag`, []string{dbLabelName}, []string{dbName}), + }) + } +} + var MDBXGauges = InitMDBXMGauges() // global mdbx gauges. each gauge can be filtered by db name var MDBXSummaries sync.Map // dbName => Summaries mapping +var MDBXGCSummaries sync.Map // dbName => GCSummaries mapping var ( ErrAttemptToDeleteNonDeprecatedBucket = errors.New("only buckets from dbutils.ChaindataDeprecatedTables can be deleted") diff --git a/db/kv/mdbx/kv_mdbx.go b/db/kv/mdbx/kv_mdbx.go index 48cc6e0f919..fe0c27432d8 100644 --- a/db/kv/mdbx/kv_mdbx.go +++ b/db/kv/mdbx/kv_mdbx.go @@ -192,6 +192,7 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { if opts.metrics { kv.InitSummaries(opts.label) + kv.InitGCSummaries(opts.label) } if opts.HasFlag(mdbx.Accede) || opts.HasFlag(mdbx.Readonly) { for retry := 0; ; retry++ { @@ -1025,6 +1026,23 @@ func (tx *MdbxTx) Commit() error { tx.db.opts.log.Error("failed to record mdbx summaries", "err", err) } + // Record GC stats as Summary metrics to capture spike distribution + // Summary naturally aggregates all observations over time windows, showing when spikes happened + pages := float64(latency.GCDetails.MaxRetainedPages) + lag := float64(latency.GCDetails.MaxReaderLag) + + // Get GC summaries for this DB instance + gcSummariesIface, ok := kv.MDBXGCSummaries.Load(string(dbLabel)) + if ok { + gcSummaries := gcSummariesIface.(*kv.GCSummaries) + gcSummaries.GCMaxRetainedPages.Observe(pages) + gcSummaries.GCMaxReaderLag.Observe(lag) + } + + if latency.GCDetails.MaxRetainedPages > 0 || latency.GCDetails.MaxReaderLag > 0 { + log.Warn("[dbg] latency.GCDetails", "MaxRetainedPages", latency.GCDetails.MaxRetainedPages, "MaxReaderLag", latency.GCDetails.MaxReaderLag) + } + //kv.DbGcWorkPnlMergeTime.Update(latency.GCDetails.WorkPnlMergeTime.Seconds()) //kv.DbGcWorkPnlMergeVolume.Set(uint64(latency.GCDetails.WorkPnlMergeVolume)) //kv.DbGcWorkPnlMergeCalls.Set(uint64(latency.GCDetails.WorkPnlMergeCalls)) diff --git a/db/kv/mdbx/util.go b/db/kv/mdbx/util.go index 952bcc0760c..a4a3846b56d 100644 --- a/db/kv/mdbx/util.go +++ b/db/kv/mdbx/util.go @@ -21,10 +21,11 @@ import ( "os" "github.com/c2h5oh/datasize" + "github.com/erigontech/mdbx-go/mdbx" + "github.com/erigontech/erigon/common/log/v3" "github.com/erigontech/erigon/db/kv" "github.com/erigontech/erigon/db/kv/dbcfg" - "github.com/erigontech/mdbx-go/mdbx" ) func MustOpen(path string) kv.RwDB { diff --git a/execution/tests/execution-spec-tests b/execution/tests/execution-spec-tests index b1d77840e3a..18f5a663a8d 160000 --- a/execution/tests/execution-spec-tests +++ b/execution/tests/execution-spec-tests @@ -1 +1 @@ -Subproject commit b1d77840e3a034d2d1c4683b2fe105dffc5db5ec +Subproject commit 18f5a663a8d3b6a05cf659ae00df48de1c6c1595 diff --git a/execution/tests/testutil/gen_difficultytest.go b/execution/tests/testutil/gen_difficultytest.go index bd79a94dc05..6cf961840f6 100644 --- a/execution/tests/testutil/gen_difficultytest.go +++ b/execution/tests/testutil/gen_difficultytest.go @@ -16,11 +16,11 @@ var _ = (*difficultyTestMarshaling)(nil) // MarshalJSON marshals as JSON. func (d DifficultyTest) MarshalJSON() ([]byte, error) { type DifficultyTest struct { - ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp"` + ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp"` ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentUncles math.HexOrDecimal64 `json:"parentUncles"` - CurrentTimestamp math.HexOrDecimal64 `json:"currentTimestamp"` - CurrentBlockNumber math.HexOrDecimal64 `json:"currentBlockNumber"` + ParentUncles math.HexOrDecimal64 `json:"parentUncles"` + CurrentTimestamp math.HexOrDecimal64 `json:"currentTimestamp"` + CurrentBlockNumber math.HexOrDecimal64 `json:"currentBlockNumber"` CurrentDifficulty *math.HexOrDecimal256 `json:"currentDifficulty"` } var enc DifficultyTest diff --git a/go.mod b/go.mod index 83ec24aa2ca..07e04cb5bf3 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ replace github.com/holiman/uint256 => github.com/erigontech/uint256 v0.0.0-20260 require ( github.com/erigontech/erigon-snapshot v1.3.1-0.20260210221902-e495954c7e78 github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116 - github.com/erigontech/mdbx-go v0.39.12 + github.com/erigontech/mdbx-go v0.40.1-0.20260225123218-e0dbe9d50909 github.com/erigontech/secp256k1 v1.2.1-0.20260218182123-377cc1bd6410 github.com/erigontech/silkworm-go v0.24.0 ) diff --git a/go.sum b/go.sum index bedecaca613..5dee21aa046 100644 --- a/go.sum +++ b/go.sum @@ -348,8 +348,8 @@ github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116 h1:KCFa2uXE github.com/erigontech/erigonwatch v0.0.0-20240718131902-b6576bde1116/go.mod h1:8vQ+VjvLu2gkPs8EwdPrOTAAo++WuLuBi54N7NuAF0I= github.com/erigontech/fastkeccak v0.1.1-0.20260222164035-95925bf94241 h1:L82GiRxJ9KhUI24BMzDkWOeKrKGyEaC9Bo+CmVqs7ag= github.com/erigontech/fastkeccak v0.1.1-0.20260222164035-95925bf94241/go.mod h1:CwJFJVKFVWpQyKSfRrQyY56IqV16sR5xnQoFThGHiZA= -github.com/erigontech/mdbx-go v0.39.12 h1:WjvPzloxXOYfRamIxt8NOB7i3/M8cSCSfWQHvMNANrE= -github.com/erigontech/mdbx-go v0.39.12/go.mod h1:tHUS492F5YZvccRqatNdpTDQAaN+Vv4HRARYq89KqeY= +github.com/erigontech/mdbx-go v0.40.1-0.20260225123218-e0dbe9d50909 h1:Av9oizuYe1/cAK/lVman8VzzV89XB/+rGqngdmBrdDI= +github.com/erigontech/mdbx-go v0.40.1-0.20260225123218-e0dbe9d50909/go.mod h1:qo3aRGnrYWdrQHnUgj7QwYQc562Hd2CCZZc/v5lLSHw= github.com/erigontech/secp256k1 v1.2.1-0.20260218182123-377cc1bd6410 h1:5YD7JJ5PaqOdjKA84lTDtQby9nbI4podqrkUhyIyFDw= github.com/erigontech/secp256k1 v1.2.1-0.20260218182123-377cc1bd6410/go.mod h1:CnigLRUsfobnTYoUzwdT/De67fw9OhTA0KTkxa+svik= github.com/erigontech/silkworm-go v0.24.0 h1:fFe74CjQM5LI7ouMYjmqfFaqIFzQTpMrt+ls+a5PxpE= diff --git a/node/interfaces b/node/interfaces index 6802ec33f3e..37b1a34d362 160000 --- a/node/interfaces +++ b/node/interfaces @@ -1 +1 @@ -Subproject commit 6802ec33f3ead7b5c497bae9900509a23905033d +Subproject commit 37b1a34d36251c41c4ebd262825a37794131f079