Skip to content

feat(gos): HLL register-change delta adapter (|2^C'−2^C|≥2^τ, never-reset) - #529

Merged
zzylol merged 1 commit into
mainfrom
split/pr-gos-hll
Jul 17, 2026
Merged

zzylol merged 1 commit into
mainfrom
split/pr-gos-hll

Conversation

@zzylol

@zzylol zzylol commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Part of the GOS per-family stack (base: CountSketch split/pr-gos-countsketch / #524). Depends on sketchlib-go #76 (InsertWithHashReportingChange). The structurally-odd family: registers are NEVER reset (MAX-merge idempotency), unlike every additive family.

Send when a register's linearized value crosses |2^C'−2^C|≥2^τ (derivations §8.7), computed with exact integer shifts (1<<C), never math.Pow. drainGosDelta serializes the pending dirty-list into a sparse RegisterDelta and touches ZERO underlying registers.

  • τ → config: reuses GosDeltaEpsilon/gos_delta_epsilon reinterpreted as τ (a doublings count); validation allows τ>0 unbounded for HLL while keeping CountSketch's ε∈(0,1). SetGosMode(tau, sites) keeps CountSketch's signature so applyGosMode drives both via one assert; sites unused for HLL.
  • Scope: DENSE HLL only. The sparse base routes through sparseInsert (no per-register change accessor), so config_validate rejects gos_delta_epsilon+hll_sparse with a boot error — a follow-up gap.
  • First-nonzero-write mitigation (send a register's first 0→nonzero write unconditionally): implemented per design-doc open item, but its small-cardinality correctness is UNVERIFIED (OctoSketch's proof is stated for large cardinality only) — tested for behavior, not correctness.

The pre-existing non-GOS EstimateCardinality() divergence path is left fully intact when GOS is off. HLL's hash-threshold sampling is kept out of the coordinated path, so no #518 interaction.

Test plan

  • never-reset (before/after register byte-equality), idempotency (re-applying stale/smaller delta never lowers estimate), first-nonzero mitigation, wake arm-once/clear, 2^τ boundary.
  • processor: TestGOSHLLInsertWakesFlush + TestConfigValidate_GosHLL.
  • build/vet/test clean in all three locations.

🤖 Generated with Claude Code

Convert HLL to the GOS insert-time delta model (design-gos-unified-edge-
telemetry.md §11, sampling-cdm-gos-derivations.md §8.7), the structurally
odd-one-out family: its state is a vector of max-registers merged by
register-wise MAX (idempotent, monotone), so — unlike every additive family
in this workstream — HLL registers are NEVER reset on send. Re-sending an
unchanged/already-known register value is harmless (max(x,x)=x), which is
exactly what makes the never-reset rule correct.

HLLWrapper (asap-precompute-go/sketches/hll.go):
  - SetGosMode(tau, _): τ is REINTERPRETED onto the existing generic
    PrecomputeConfig.GosDeltaEpsilon knob (a count of "doublings", not
    CountSketch's ε budget) — HLL and CountSketch never share a live sketch,
    so overloading the one float64 field avoids a second family-specific
    config field. The uint32 sites arg is accepted for a uniform SetGosMode
    shape but unused (HLL's formula has no multi-site k term).
  - Insert path routes UpdateValue/UpdateBytes through sketchlib-go's new
    InsertWithHashReportingChange; a register that mechanically changed is
    checked against |2^C'-2^C| >= 2^τ (exact integer shifts, not math.Pow)
    and, if crossed, queued in gosDirty with its CURRENT value. gosLastSent
    tracks the per-register last-sent baseline the sketch itself cannot
    (registers are never reset, so "since last sent" isn't readable off the
    register).
  - First-nonzero-write mitigation (design doc §12 open item 4): a register's
    first-ever nonzero write (last=0, cur>0) is sent unconditionally
    regardless of τ. This is EXPLICITLY UNVERIFIED for the small-cardinality
    regime per the design doc — implemented because it's cheap and proposed,
    not because it's proven.
  - ComputeDeltaAgainst drains gosDirty into a sparse RegisterDelta WITHOUT
    touching a single underlying register (the critical correctness
    difference from CountSketch, which resets cells to 0 on send); dedups to
    each register's latest value and sorts ascending for the varint wire form.
  - gosWake/ConsumeWakeSignal wire the insert-time crossing to the runtime's
    out-of-cycle sub-window flush. Reset clears per-window GOS state but keeps
    gosTau (mode config, not accumulation state).

Runtime (precompute.go, config.go): applyGosMode + the sub-window Gate-1
bypass now cover SketchTypeHLLSketch when GosDeltaEpsilon>0; the pre-existing
non-GOS EstimateCardinality() divergence path is left fully intact when GOS
is off.

Processor (asapedgeprocessor): the dense-HLL factory primes SetGosMode at
series creation; config_validate accepts gos_delta_epsilon (τ, no (0,1)
upper bound) on family=hll but rejects it with hll_sparse (the sparse base
has no per-register GOS path — this PR is scoped to dense HLL). CountSketch's
ε (0,1) bound is preserved.

Tests: sketchlib-level detection + first-nonzero mitigation + sampling;
wrapper-level never-reset assertion (verifies raw registers unchanged after a
drain — the opposite of every other family's test), MAX-merge idempotency,
wake-signal, Reset semantics; processor-level end-to-end
TestGOSHLLInsertWakesFlush (ConsumeMetrics alone produces a flush with no
SubWindowInterval and no manual wakeSubWindow) plus config-validation cases.

Uses sketchlib-go feat/gos-hll-primitive @ bf7828357a8125413d905a22c4a0446cf642ac76

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@zzylol
zzylol force-pushed the split/pr-gos-hll branch from b71ed93 to 39949d2 Compare July 17, 2026 02:48
@zzylol
zzylol changed the base branch from split/pr-gos-countsketch to split/pr-gos-kll July 17, 2026 02:48
@zzylol
zzylol changed the base branch from split/pr-gos-kll to main July 17, 2026 15:47
@zzylol
zzylol merged commit 52b3f78 into main Jul 17, 2026
@zzylol
zzylol deleted the split/pr-gos-hll branch July 17, 2026 15:52
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