This repository was archived by the owner on Aug 11, 2026. It is now read-only.
perf: project only the KOTH detail keys the retest path reads - #675
Closed
Peyton-Spencer wants to merge 2 commits into
Closed
perf: project only the KOTH detail keys the retest path reads#675Peyton-Spencer wants to merge 2 commits into
Peyton-Spencer wants to merge 2 commits into
Conversation
_current_koth_entries selected every eligible agent's whole score telemetry
blob and read three fields out of it: composite_stderr (via _ledger_stderr)
and the legacy confirmation_seeds/confirmation_composites pair. The blob
averages ~22KB a row on bench v8.
Only the retest path pays this. _current_koth_entries is reached solely
from _current_emission_set and _current_retest_cohort, so the canonical
/validator/job lane never touches it -- which is exactly the asymmetry
observed in production: new submissions were being scored normally while
the continual-retest lane crawled.
Measured on the live prod worker with py-spy (2383 samples, 30s):
- 41% of CPU inside asyncpg's JSONB decoder (raw_decode the top leaf)
- /top5-confirmation-job slowest request 151,884ms -- 152 seconds
- /validator/job slowest 20-40s over the same period
- the decode is charged to the event-loop callback, not the awaiting
coroutine, which is why no request-level metric ever showed it
Add `details_keys=` to list_eligible_ledger: Postgres builds a details
object from only the named keys, so the rest never detoasts, never crosses
the wire, and never reaches the JSON decoder. Absent keys arrive as None,
which every reader of these three already treats as absent.
This is the same class of fix as the include_details=False pair, but for a
consumer that genuinely needs part of the blob rather than none of it.
Refs ditto-assistant/ditto-subnet#388.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI typechecks the tree; LedgerRow.details is dict | None, so the absent-key test needed the same isinstance narrowing its sibling already had. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 7, 2026
Contributor
Author
|
Closing unmerged: superseded by the monorepo cutover. Production is now served from
Merging here would land the fix on a branch nothing ships, which is worse than closing: it makes this repo look maintained and invites a deploy from it. See ditto-subnet#566 for the cutover follow-ups. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Third in the live hotfix stack (on top of #674, which is on #673). This is the one the profiler actually pointed at.
_current_koth_entriesselected every eligible agent's entire score telemetry blob and read exactly three fields out of it:composite_stderr(via_ledger_stderr) plus the legacyconfirmation_seeds/confirmation_compositespair. That blob averages ~22KB a row on bench v8, across every eligible agent.Only the retest path pays for it.
_current_koth_entriesis reached solely from_current_emission_setand_current_retest_cohort; the canonical/validator/joblane never calls it. That is precisely the asymmetry seen in production — new submissions were being scored normally while the continual-retest lane crawled.Measured on the live prod worker
py-spy record, 2383 samples over 30s,--nonblocking:raw_decodethe top leaf frame by a wide margin/validator/top5-confirmation-jobslowest request: 151,884ms — 152 seconds. Validators are timing out before a ticket returns, which is why the lane looks dead rather than slow./validator/jobslowest over the same period: 20-40sThe change
list_eligible_ledger(details_keys=(...))has Postgres build adetailsobject from only the named keys, so the remainder never detoasts, never crosses the wire, and never reaches the JSON decoder. Absent keys arrive asNone, which all three readers already treat as absent.Same class of fix as the existing
include_details=False, but for a consumer that needs part of the blob rather than none of it._KOTH_DETAIL_KEYSsits directly above the function that reads them, with a comment tying the tuple to its readers.Validation
uv run pytest ditto/tests/api_server/endpoints/ -q→ 1150 passeduv run pytest ditto/tests/db/queries/ ditto/tests/api_server/endpoints/test_validator.py -q→ 850 passed, 4 skippedruff check/ruff format --check/mypy→ cleanThe validator endpoint suite covers the KOTH and retest paths, so stderr and legacy-confirmation behaviour are exercised against the narrowed projection. New tests pin that only requested keys are returned and that an absent key arrives as
None.Honest scope
This attacks per-request cost on the retest path. It does not reduce the number of allocator recomputations — subnet#388's batched claim contract is still unimplemented and is still the structural fix. Whether 152s becomes acceptable or merely better is an empirical question; I'll post before/after from the same profiler after deploy.