core, core/state: instrument BAL slow-block metrics#34861
Conversation
|
cc: @jwasinger this should do the job. LMK what's your take :) |
| accountReadNS atomic.Int64 | ||
| storageReadNS atomic.Int64 |
There was a problem hiding this comment.
db read operations should be highly concurrent here. is the aggregate time from all operations a useful metric to track?
There was a problem hiding this comment.
hmmmm. fair point it may be not. We had it in the original spec IIRC. And I think it was just kept? It can show somewhat valuable things like any tradeoffs on account vs. storage read optimizations we might be missing (?).
Unsure. What's your take? I also wonder what @rjl493456442 thinks here.
|
Thanks for this! Mostly looks good. I will push some small cleanups to it tomorrow and then merge it. |
I spoke too soon.. ended up getting sick from the plane flight and/or airports on the trip back home. |
…s, surface more metrics including prefetcher time (#34892) Adapts some of the changes from #34861 . Some other metrics which are recorded manually during execution in that PR, but can be deduced from the BAL are TBD. I've added two bal feature flags: * `--bal.prefetchworkers <uint>`: this tunes the number of concurrent go-routines that will be used to perform state fetching tasks by the BAL prefetcher. Default is `runtime.NumCPUs`, the current behavior in `bal-devnet-3`. * `--bal.blockingprefetch`: If set, state prefetching will block the execution of transactions and state root update. --------- Co-authored-by: CPerezz <cperezz19@pm.me>
d0005c1 to
3f5e27e
Compare
|
@jwasinger this should be ready! |
Populates per-block state read/write counts in slow-block JSON for BAL blocks (which ethereum#34892 left as TBD), and adds reader-level read timing. Builds on top of bal-devnet-3 — most of the PR's earlier slow-block log infrastructure was adapted into upstream by that commit, so this change is now scoped to the metric population that the BAL alone can derive. - BAL helpers: BlockAccessList.{UniqueAccountCount, UniqueStorageSlotCount, WrittenCounts}. WrittenCounts walks the BAL once and returns the block-aggregate write counts. - Reader-level read timing: *reader times all synchronous Account/Storage/ Code/CodeSize calls via atomic counters; exposed via ReadTimes() ReadDurations and the new state.ReadTimer interface. Replaces StateDB- level AccountReads/StorageReads/CodeReads tracking (the StateDB shouldn't time its dependencies — the reader is where the I/O happens). - Reader-level code-load dedup: *reader.codeLoaded sync.Map records the first-seen byte length per address; CodeLoads() returns (count, bytes). Exposed via state.CodeLoadTracker. Replaces StateDB CodeLoaded/ CodeLoadBytes tracking and the SnapshotCodeLoads aggregation pattern. - BALStateTransition: caches BlockAccessList.WrittenCounts() once at construction; tracks accountDeleted/storageDeleted atomics for the parallel root-pass (the BAL alone can't distinguish a selfdestruct from a balance/nonce reset). Exposes Deletions() DeletionCounts. Drops the older accountUpdated/storageUpdated/codeUpdated/codeUpdateBytes counters (now derived from WrittenCounts). - BAL block stats path (blockchain.go): populates StateCounts directly — AccountUpdated = WrittenCounts.Accounts - Deletions.Accounts (same for storage). AccountLoaded/StorageLoaded come from BAL. CodeLoaded/ CodeLoadBytes come from the shared *reader (deduplicated across phase StateDBs naturally because they share one reader instance). - Non-BAL block stats path: read durations come from the reader; counts from StateDB fields. StorageUpdated/StorageDeleted unified to int width. - Hard type assertions: state.ReadTimer / state.CodeLoadTracker / state.ReaderStater consumers use direct casts (no silent zero fallback) — every Reader chain in production satisfies these interfaces. - Meter alignment: account/storage Updated meters subtract Deletions to avoid double-reporting blocks under both Update and Delete dashboards.
- Pre-BAL path keeps StateDB synchronous read-time accumulators (AccountReads, StorageReads, CodeReads, CodeLoaded, CodeLoadBytes) so Execution = ptime - reads stays well-formed under single-thread execution. - BAL path drops aggregate reader read-times; under parallel workers they sum across goroutines and aren't a wall-clock proxy. - Delete dead PrefetchReadTimes/WaitPrefetch forwarders on *reader and the now-unused ReadTimer/ReadDurations scaffolding. - Add regression test for EIP-7702 delegation clear: empty []byte code in the BAL must reset CodeHash to EmptyCodeHash.
Stripped by 3f5e27e alongside the StateDB ones. The struct doc and per-field descriptors (rootHash, diffs, prestates, tries) come back.
…ocks For BAL blocks AccountReads/StorageReads/CodeReads stay zero by design, so the slow-block JSON state_read_ms read 0 — misleading to cross-client consumers. Sum s.Prefetch (the prefetcher's elapsed time) into the field; it's already zero on the pre-BAL path so the formula is unchanged there. Also gofmt -w on reader.go and reader_eip_7928.go (trailing blank lines left over from earlier cleanup).
The Account and Storage methods on *reader were pure forwarders to the embedded StateReader; Go's method promotion makes them redundant. Remove the EIP-7702 delegation-clear regression test; coverage is deferred to the execution-spec test suite, which already exercises the BAL apply path via tests/block_test_util.go.
9bd26a3 to
3eafb4e
Compare
A first attempt to get the entire slow_blocks to be BAL¶llel-exec-aware.
balJSON field isomitempty.