mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
core/state: forward prefetcher read times through the reader aggregator
Without this, the inline interface assertion in processBlockWithAccessList silently fell through (the prefetchReader returned by ReaderEIP7928 is a *reader wrapper, not the inner *prefetchStateReader), causing the prefetcher contribution to state_read_ms to drop to zero in production. Mirrors the existing GetStateStats forwarding pattern. Adds a regression test that asserts *reader exposes PrefetchReadTimes via the BAL chain, plus a fallback test for non-prefetch readers.
This commit is contained in:
parent
812fa198c3
commit
6b1ea9a498
2 changed files with 51 additions and 0 deletions
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/overlay"
|
"github.com/ethereum/go-ethereum/core/overlay"
|
||||||
|
|
@ -563,3 +564,15 @@ func (r *reader) GetStats() ReaderStats {
|
||||||
StateStats: r.GetStateStats(),
|
StateStats: r.GetStateStats(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrefetchReadTimes returns the prefetcher's accumulated read times if the
|
||||||
|
// underlying state reader exposes them (e.g. *prefetchStateReader). Returns
|
||||||
|
// zero if the wrapped reader doesn't track these (sequential paths, tests).
|
||||||
|
func (r *reader) PrefetchReadTimes() (account, storage time.Duration) {
|
||||||
|
if pr, ok := r.StateReader.(interface {
|
||||||
|
PrefetchReadTimes() (time.Duration, time.Duration)
|
||||||
|
}); ok {
|
||||||
|
return pr.PrefetchReadTimes()
|
||||||
|
}
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,3 +290,41 @@ func TestPrefetchStateReaderForwardsStats(t *testing.T) {
|
||||||
t.Fatalf("forward mismatch: got %+v, want %+v", gotStats, stats)
|
t.Fatalf("forward mismatch: got %+v, want %+v", gotStats, stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestReaderForwardsPrefetchReadTimes locks down that the *reader aggregator
|
||||||
|
// (the type returned by ReaderEIP7928) exposes PrefetchReadTimes via the
|
||||||
|
// inner *prefetchStateReader. Without the forwarding method on *reader,
|
||||||
|
// callers that hold a Reader interface would not see the prefetcher's
|
||||||
|
// accumulated read times even though the prefetcher tracks them.
|
||||||
|
func TestReaderForwardsPrefetchReadTimes(t *testing.T) {
|
||||||
|
stub := newRefStateReader()
|
||||||
|
cached := newStateReaderWithCache(stub)
|
||||||
|
withStats := newStateReaderWithStats(cached)
|
||||||
|
prefetch := newPrefetchStateReaderInternal(withStats, nil, 1)
|
||||||
|
|
||||||
|
// Seed timer values directly on the prefetcher.
|
||||||
|
prefetch.accountReadNS.Store(123)
|
||||||
|
prefetch.storageReadNS.Store(456)
|
||||||
|
|
||||||
|
// Wrap in *reader the way ReaderEIP7928 does (with a nil code reader for
|
||||||
|
// brevity; PrefetchReadTimes only inspects the state side).
|
||||||
|
r := newReader(nil, prefetch)
|
||||||
|
|
||||||
|
a, s := r.PrefetchReadTimes()
|
||||||
|
if a != 123 {
|
||||||
|
t.Errorf("account: got %v, want 123", a)
|
||||||
|
}
|
||||||
|
if s != 456 {
|
||||||
|
t.Errorf("storage: got %v, want 456", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestReaderPrefetchReadTimesNonPrefetch verifies the safe zero fallback when
|
||||||
|
// the wrapped state reader doesn't expose PrefetchReadTimes (sequential path).
|
||||||
|
func TestReaderPrefetchReadTimesNonPrefetch(t *testing.T) {
|
||||||
|
r := newReader(nil, newRefStateReader())
|
||||||
|
a, s := r.PrefetchReadTimes()
|
||||||
|
if a != 0 || s != 0 {
|
||||||
|
t.Errorf("expected (0, 0), got (%v, %v)", a, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue