erigontech / erigontech/erigon
execution, db: simplify cache publication and hot-path plumbing
- Dominant language
- Go
- Stars
- 3.6k
- Forks
- 1.5k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 455
Description
## Goal
Track independent simplifications and performance opportunities left after #23095. None of these is required for the correctness of #23095, and each can be reviewed separately.
## Candidates
### Treat missing commitment files as files end zero
`Aggregator.beginCacheFilesPublication` currently skips BranchCache publication when no commitment file is visible, while `closeDirtyFilesNoReopen` resets BranchCache explicitly.
Always call `BranchCache.BeginFilesPublication`, using end zero when the commitment view is absent. This would give file extension, lowering, and complete unmapping one publication protocol and remove the manual reset from `closeDirtyFilesNoReopen`.
Add a regression test proving that publication of an empty commitment-file view revokes the old view and clears incompatible entries.
### Avoid copying every adaptive-pin miss snapshot
`AdaptivePinController.PlanBlock` copies the map returned by `snapshotMisses`, then deletes active contracts from one copy before selecting promotion candidates.
Keep the original snapshot as `plan.observedMisses` for abort restoration, and make candidate selection skip contracts that remain active. This removes one map allocation and one full copy per block. Tests must cover successful publication and abort restoration.
### Derive cache views once per `TemporalPutDel`
`temporalGetter` derives its cache views once, but `temporalPutDel` calls the direct `SharedDomains` write methods. Writes with `prevVal == nil` can therefore derive the same transaction identity repeatedly while resolving previous values.
Store one cache-view pair in `temporalPutDel` and reuse it for previous-value reads. Measure the writer path before and after because this changes hot-path plumbing even though the transaction's state version and pinned files are stable.
### Centralize typed CodeCache access
`StateCache` repeatedly asserts that its code-domain slot is a `*CodeCache`, although the constructor establishes that invariant. A private typed accessor can put the defensive check in one place and make the code-specific paths consistent. This is a small readability cleanup; it should not add another pointer to `StateCache` unless measurement justifies it.
### Evaluate one lock for `GenerationGate`
`GenerationGate` uses `publicationMu` to order transitions and `admissionMu` to drain or block fills. One `sync.RWMutex` could represent both rules: fills take the read lock, while initialization, reset, close, canonical publication, and backing-file publication take the write lock.
This would reduce the lock-state proof and remove unlock/relock choreography. Do not adopt it without contention benchmarks: Go writer preference may make fills block earlier when publications queue, even though cache hits remain lock-free.
## Non-goals
- Do not merge StateCache and BranchCache generation gates. Their backing-file identities change independently, so a shared gate would cause unnecessary invalidation.
- Do not add another generic publisher layer. `GenerationGate` and `CanonicalPublisher` already share the common lifecycle; state updates and branch/adaptive-pin updates remain meaningfully different.
- Do not remove explicit unwind, file-publication, and concurrency scenarios merely to reduce test diff size.
## Suggested order
1. Normalize the empty commitment-files publication.
2. Remove the adaptive miss-map copy.
3. Centralize CodeCache access.
4. Benchmark cached `TemporalPutDel` views.
5. Benchmark the single-lock `GenerationGate` design before deciding whether its simpler state machine is worth the scheduling change.
Contributor guide
Assessment
This issue has not been assessed yet.