perf(clones): decode clone tokens in one pass; validate each payload once - #1577
ScriptedAlchemy wants to merge 5 commits into
Conversation
A retryable graph activation used to erase the prepared serving candidate, and an unfinished clone-fingerprint successor withheld the same seat after exact and lexical owners were ready. Keep the candidate in both cases so search can move off the predecessor while graph retries. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
Serde's internally tagged derive buffers every clone-body token object into an owned `Content` map before it can dispatch on `kind`. Clone-body token streams are the largest repeated record in a sealed generation, so that buffer is paid millions of times per publish, restore, and clone-census read. Keep the derived `Serialize` so the wire form stays byte-identical and write `Deserialize` by hand: one pass over the object, no intermediate buffer, and the same refusals for an unknown or duplicated member, a missing or unknown `kind`, and a member that does not belong to the tagged variant. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
`clone_body_payloads` is keyed by payload digest, so one row backs every occurrence sharing that body. The census joined the two tables and re-derived a payload's four canonical digests once per occurrence, so a generated 768-file corpus verified 128 distinct payloads 98,304 times — about 1.2 s of single-threaded work inside the status read that holds the scheduler lock. Validate the payload table once, retain only the rename coverages the per-occurrence counters distinguish, and classify occurrences against that verified index. Both prior refusals are kept and two are added: a payload whose blob disagrees with its stored digest, and an occurrence whose payload row is absent, which the inner join used to drop from the totals. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
|
Compose with #1570, which moved clone-body token streams to `Arc<[ConservativeCloneTokenV1]>` shared between the extracted body and its payload. That change is container-level and the token element is untouched, so the hand-written element `Deserialize` here layers on top of it: #1570 removes the extraction-side token copy, this removes the decode-side serde buffer. The only conflict was the import block, where both additions are needed. Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
|
Superseded by #1882, which ports the measured clone-census commit (, 2.282 s to 0.310 s over 98,304 occurrences). The hand-written commit () was dropped: 157 lines of byte-compatibility maintenance for a claimed 17% on one decode step that the census port already removes from its hottest path. The seat-through-retryable-activation fix shared by this branch is #1877. |
|
Correction to the close note, which lost its code spans: superseded by #1882, which ports the measured clone-census commit |
Two measured, wire-preserving cuts to the clone-body codec that the
background_refresh_and_reopen_report_only_servable_generationsjourney drives98,304 times per generation. These compose with #1570 (merged) rather than
overlapping it: #1570 removed the extraction-side token copy by sharing
Arc<[ConservativeCloneTokenV1]>between an extracted body and its payload;this removes the decode-side serde buffer and the census-side repeated
payload verification. The token element type is untouched by #1570, so the two
changes layer cleanly — the merge commit here resolves their only overlap (one
import block).
1. Clone tokens decode without serde's tagged buffer
ConservativeCloneTokenV1is internally tagged, so serde's derivedDeserializebuffers every token object into an ownedserde::__private::de::Contentmap before it can dispatch onkind. #1570'sArc<[_]>sharing is extraction-side only: on the restore path every sealedsegment still decodes its own token objects, and a 768-file generated corpus
decodes 3.5 M of them per generation, plus again on every clone-census read and
clone-successor pass.
Serializestays derived, so the wire form is byte-identical and no sealedformat revision moves.
Deserializeis hand-written as a single-pass visitorkeeping every refusal the derive made: unknown member, duplicated member,
missing
kind, unknown tag, and a member that does not belong to the taggedvariant.
clone_body_tokens.rscovers the wire form, member-orderindependence, and all ten refusals.
Measured on
pub fn refresh_probe_NNNN_NNN(input: u32) -> u32 { input + N }× 128 (one fixture file, 2,304 tokens), release profile, both arms on top of
#1570:
2. The clone census validates each stored payload once
clone_body_payloadsis keyed by payload digest, so one row backs everyoccurrence that shares that body.
read_clone_index_censusjoined the twotables and called
CloneBodyPayloadV1::validate()— four canonical SHA-256passes over the token streams — once per occurrence. The generated corpus
stores 98,304 occurrences over 128 distinct payloads, so the census performed
98,304 validations to discharge 128 obligations: about 1.2 s of
single-threaded work, inside the
worktree_freshnessread that holds thescheduler lock and that the journey polls in a spin loop.
The payload table is now validated once up front; only the rename coverages
the per-occurrence counters distinguish are retained, and occurrences are
classified against that verified index. Both prior refusals are preserved and
two are added:
payload_digestdisagrees with its stored row key;dropped from
source_bodiessilently.Reviewing this diff
Only three files are this change:
crates/tracedecay-code-extraction/src/clone_body.rscrates/tracedecay-code-extraction/tests/main/clone_body_tokens.rscrates/tracedecay-query/src/retrieval/lexical/projection/artifact/clone_census.rsThe three
code_index_scheduler/registry*files in the diff are inherited fromb80dd58— the tip ofcursor/seat-through-retryable-activation-f5c7, whichthis work started from and which is under review as #1562 (and extended by
#1567). They are not part of this change and disappear from the diff once #1562
lands.
Verification (composed tree,
master+ this PR)cargo test --release -p tracedecay-code-extraction --test main— 585 passed, 0 failed (includes the new wire-form and refusal coverage).cargo test --release -p tracedecay-code-index --lib— 255 passed, 0 failed (includesstreaming_file_segment_bytes_match_the_value_encoder, the segment byte-parity guard).cargo test --release -p tracedecay-code-index --test code_index_suite -- partitioned sealed clone— 41 passed, 0 failed (includespartitioned_codec_has_stable_bytes_and_round_trips,sealed_restore_reencodes_identically_at_serial_and_parallel_widths,carried_forward_clone_bodies_admit_through_the_reused_sealed_segment).cargo test --release -p tracedecay-query --test search_quality_suite -- clone—v16_clone_payloads_are_content_addressed_and_postings_pagepassed.cargo clippy --release -p tracedecay-code-extraction -p tracedecay-query --all-targets— clean.cargo fmt --all -- --check— the four reported diffs are incode_index_generations/locking.rsandlifecycle_lease.rs, untouched here and already drifted onmaster.cargo test --release -p tracedecay-code-index-runtime --lib -- clonegave 13 passed / 2 failed; both failures (query_admission_serves_v14_while_clone_successor_is_pending,expired_source_proof_reschedules_pending_clone_backfill) reproduced identically with the changed files reverted tob80dd58, so they are not introduced here.No sealed generation format revision, segment digest, or clone payload digest
changes, and
RECEIPT_TIMEOUTis untouched. Nothing merged.