Skip to content

feat(delta): per-window DDSketch delta producer (delta-against-empty) - #456

Merged
zzylol merged 2 commits into
mainfrom
feat/delta-enablement-ddsketch-producer
May 26, 2026
Merged

zzylol merged 2 commits into
mainfrom
feat/delta-enablement-ddsketch-producer

Conversation

@zzylol

@zzylol zzylol commented May 26, 2026 •

Copy link
Copy Markdown
Contributor

Delta enablement, Phase 1 (producer side), DDSketch-first — per the delta-baseline contract (docs/delta-baseline-contract.md §3).

The edge tumbling window already resets per-series sketch state each window. This makes the delta match: after each window close, the SnapshotCache outbound base is reset to empty, so each window's delta is computed against an empty base = that window's own state encoded as a delta (no cross-window subtraction). The backend (Phase 2) then rotates its per-series base at the window boundary, giving a clean per-window total. Self-healing: a dropped delta corrupts only one window.

  • asap-precompute-go/snapshot_cache.go + sketches/ddsketch.go: opt-in DeltaAgainstEmptyBase(); reset base to empty after window-close emit. CMS/CountSketch/HLL/KLL unchanged (legacy always-refresh).
  • asap-precompute-rs/{snapshot_cache,precompute,sketches/ddsketch}.rs: mirror via Sketch::delta_against_empty_base() (default None); closed the Rust delta-emit gap (compute_delta_against now emits a real bucket-delta; apply_delta dispatches full vs DDSketchDelta).
  • DDSketch-only this phase. Tests: delta-against-empty round-trips to the window snapshot; consecutive windows emit their own state (no cross-window subtraction). Go↔Rust byte-parity verified (345-B frame).

Depends on asap_sketchlib's DdSketch::compute_delta (merged). Backend per-window base rotation (Phase 2) is a separate ASAPQuery-backend PR.

🤖 Generated with Claude Code

…-against-empty)

Implements the PRODUCER half of "Option A" delta enablement
(delta-baseline-contract.md §3) for DDSketch only — the first rollout
family. The edge tumbling window already resets per-series sketch state
every window (window.go:rotateLocked / window.rs); that is unchanged.

When delta transmission is ON, the edge now emits each window's own
DDSketch state as a delta computed against an EMPTY base (no cross-window
subtraction). After each window-close emit, the SnapshotCache resets the
cached outbound base to the empty-sketch snapshot, so the next window's
ComputeDelta diffs against empty = that window's full per-window sketch
encoded as a delta. This is what makes the backend's (future) per-window
base rotation correct.

Changes:
- snapshot_cache.go / snapshot_cache.rs: after a window-close emit, if the
  sketch opts in to Option-A (DDSketch only, via the new
  emptyBaseDeltaSketch type-assertion in Go / Sketch::delta_against_empty_base
  default-None trait method in Rust), reset the cached base to the
  empty-sketch snapshot. The non-delta (full) path and the other families
  (CMS / CountSketch / HLL / KLL) are unchanged — they keep legacy
  always-refresh.
- sketches/ddsketch.go: add DeltaAgainstEmptyBase() returning an empty
  DDSketch envelope.
- sketches/ddsketch.rs: implement the previously-stubbed compute_delta_against
  (it returned is_full=true and never emitted a delta) using asap_sketchlib's
  DDSketch bucket-delta compute; add delta_against_empty_base() and teach
  apply_delta to dispatch full-envelope vs DDSketchDelta-proto payloads.

The emitted DDSketch delta frame is byte-identical between Go and Rust for
identical window state (verified: 345-byte frame for input 1..=50, α=0.01)
— closes part of #243.

Tests:
- Go (sketches/ddsketch_test.go) + Rust (snapshot_cache.rs): delta-against-empty
  round-trips to the window's full state, quantiles within relative-ε; two
  consecutive windows each emit their OWN state (no cross-window subtraction).

NOTE: this depends on a new DdSketch::compute_delta / apply_delta_bytes +
DDSketchDelta proto message added to asap_sketchlib (separate branch); the
commit here keeps the normal relative dep paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol zzylol changed the title feat(delta): Option-A producer — per-window DDSketch deltas (delta-against-empty) feat(delta): per-window DDSketch delta producer (delta-against-empty) May 26, 2026
Comment-only edit removing the internal codename from the
per-window-delta producer comments across the Go and Rust
precompute sources. No logic, API, or test changes; the
delta-baseline-contract.md §3 references are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit 32998d8 into main May 26, 2026
@zzylol
zzylol deleted the feat/delta-enablement-ddsketch-producer branch May 26, 2026 15:28
zzylol added a commit that referenced this pull request May 26, 2026
…457)

DDSketch already opts in to per-window delta-against-empty (#456). This
extends the same opt-in to CountMinSketch, CountSketch, and HLL on both
edge runtimes; KLL stays full-only and DDSketch is unchanged.

asap-precompute-go (sketches/{cms,countsketch,hll}.go): each wrapper now
implements DeltaAgainstEmptyBase(), returning the encoded empty-sketch
snapshot the SnapshotCache caches as the outbound base after each
window-close emit. The next window's ComputeDeltaAgainst (already wired
to the sketchlib-go ComputeDelta for each family) then diffs against an
empty base, so each window's delta carries that window's own per-window
state — no cross-window subtraction. CMS msgpack mode (which cannot
carry deltas) returns a nil base to keep legacy always-refresh; the
SnapshotCache now treats a nil/empty empty-base as "fall through to
legacy refresh".

asap-precompute-rs (src/sketches/{cms,countsketch,hll}.rs): each wrapper
implements delta_against_empty_base() and a real compute_delta_against
that decodes the prior envelope and diffs via the asap_sketchlib
compute_delta for that family (CMS/CountSketch cell deltas, HLL register
delta), with a full-snapshot fallback on empty/undecodable prior. Each
apply_delta now dispatches on payload shape (full-state envelope vs raw
delta proto) via apply_delta_bytes, mirroring the DDSketch wrapper. The
stale sketches/mod.rs "always-full" caveat is updated.

Tests (mirroring DDSketch's): for each family, applying the emitted
delta to an empty base reconstructs the window's state, and consecutive
windows emit their own state (no cross-window subtraction) — Go in
sketches/*_test.go, Rust in snapshot_cache.rs. HLL's disjoint-window
test pins that the empty-base reset defeats register-MAX leakage.

Depends on asap_sketchlib#59 (CMS/CountSketch/HLL compute_delta /
apply_delta_bytes; the underlying codec is the byte-parity twin of the
sketchlib-go delta codec). The backend base rotation (#346) is already
sketch-agnostic, so no backend change is needed.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant