Skip to content

phase3(parity): un-ignore countsketch byte-parity test, route wrapper through INT64/L2 - #253

Merged
zzylol merged 1 commit into
mainfrom
phase3/cross-parity-unignore-countsketch
May 5, 2026
Merged

zzylol merged 1 commit into
mainfrom
phase3/cross-parity-unignore-countsketch

Conversation

@zzylol

@zzylol zzylol commented May 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Pairs with asap_sketchlib PR #44, which ports sketchlib-go::common.HashSpec / DeriveIndex / DeriveSign into a new public module asap_sketchlib::common::hashspec and refactors CountSketch::update to feed the matrix through the same packed-u64 hash-once → bit-slice-rows pipeline Go uses. With that upstream fix landed the matrix layout matches Go cell-for-cell. The remaining gap is wrapper-side: the Rust wrapper was emitting a CountSketchState with counter_type = FLOAT64 + counts_float, while Go's CountSketch.SerializePortable emits counter_type = INT64 + counts_int + per-row l2.

Changes

  • asap-precompute-rs/src/sketches/countsketch.rs: CountSketchWrapper::build_state now mirrors Go's SerializePortable — emit packed sint64 counts_int (Opt-2 in Go, 4–8× smaller than f64 for typical counter values) and per-row L2 norms (l2[r] = sum_c counts[r][c]^2). Both fields are required for byte parity; without them the envelope diverges in counter_type, counts_*, and l2 simultaneously.
  • integration/parity/golden_test.go: the CountSketch fixture generator now strips Producer / HashSpec (matching the DDSketch / KLL / HLL cases) and clears HhKeys (the Rust wrapper does not maintain a Space-Saving candidate tracker, so this list cannot be reproduced; downstream rebuilds TopK from the merged matrix anyway).
  • asap-precompute-rs/tests/cross_language_parity.rs: removes the #[ignore] on countsketch_byte_parity_with_go.

Test plan

  • cargo test --test cross_language_parity countsketch_byte_parity_with_go (against asap_sketchlib PR feat: memory pools in otel collector processors #44 branch) passes byte-equality against the regenerated golden.
  • Full cargo test for asap-precompute-rs passes (43 + 11 + 5 + 27 tests; 2 unrelated KLL / CMS parity tests still ignored pending their own PRs).
  • cargo clippy --all-targets -- -D warnings clean.
  • Regenerated integration/parity/golden/countsketch_envelope.bin (1577 bytes; gitignored) via GOLDEN_REGEN=1 go test -run TestGenerateGoldenFixtures/CountSketch ./integration/parity/....
  • Merge after asap_sketchlib PR feat: memory pools in otel collector processors #44 lands and the local-path dep resolves to that commit on origin/main.

Closes part of #243.

🤖 Generated with Claude Code

… through INT64/L2

Pairs with asap_sketchlib PR #44, which ports
`sketchlib-go::common.HashSpec` / `DeriveIndex` / `DeriveSign` into a
new public module `asap_sketchlib::common::hashspec` and refactors
`CountSketch::update` to feed the matrix through the same packed-`u64`
hash-once → bit-slice-rows pipeline that Go uses. With that upstream
fix landed, the matrix layout matches Go cell-for-cell and the
remaining gap is wrapper-side: the Rust wrapper was emitting a
`CountSketchState` with `counter_type = FLOAT64` + `counts_float`,
while Go's `CountSketch.SerializePortable` emits
`counter_type = INT64` + `counts_int` + per-row `l2`.

This commit:

- Updates `CountSketchWrapper::build_state` to mirror Go's
  `SerializePortable`: emit packed sint64 `counts_int` (Opt-2: 4–8×
  smaller than f64 for typical small-integer counter values) and
  per-row L2 norms derived as `l2[r] = sum_c counts[r][c]^2`. Both
  fields are required for byte parity; without them the envelope
  diverges in `counter_type`, `counts_*`, and `l2` simultaneously.
- Updates `integration/parity/golden_test.go::TestGenerateGoldenFixtures`
  → `t.Run("CountSketch", …)` to strip `Producer` / `HashSpec`
  metadata before marshalling (matching the DDSketch / KLL / HLL
  cases) and to clear `HhKeys` (the Rust wrapper does not maintain a
  Space-Saving candidate tracker, so this list cannot be reproduced;
  downstream rebuilds TopK from the merged matrix anyway).
- Removes the `#[ignore]` from
  `cross_language_parity::countsketch_byte_parity_with_go`. Regenerate
  the golden fixture with
  `GOLDEN_REGEN=1 go test -run TestGenerateGoldenFixtures ./integration/parity/...`
  and the test passes byte-equality against
  `integration/parity/golden/countsketch_envelope.bin`.

Closes part of #243.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit b147538 into main May 5, 2026
zzylol added a commit that referenced this pull request May 5, 2026
…nerator (#254)

## Summary

Closes the last byte-parity gap from #243 and
fixes a latent inconsistency in the HLL fixture generator that PR #252
(HLL un-ignore) missed.

## CMS un-ignore (the original Phase 3 step 3 follow-up)

Pairs with asap_sketchlib PR #45, which ports the wire-format
`CountMinSketch::update` / `::estimate` through the shared
`asap_sketchlib::common::hashspec` pipeline (`HashSpec::default()` →
single XXH3-64-with-seed → per-row `derive_index` over a
power-of-two-rounded column mask). With that upstream fix landed the
matrix layout now matches Go cell-for-cell. The remaining gap was
wrapper-side: the Rust wrapper was emitting a `CountMinState` with
`counter_type = FLOAT64` + `counts_float`, while Go's
`CountMinSketch.SerializeProtoBytesFO` emits the Frequency-Only
payload with `counter_type = INT64` + `counts_int` + per-row `l1` /
`l2` norms (the `Sum_*` mode is reserved for weighted streams).

- `asap-precompute-rs/src/sketches/cms.rs`: `CMSWrapper::build_state`
  now emits the FO payload — `counter_type=INT64`, packed sint64
  `counts_int`, per-row `l1[r] = sum_c counts[r][c]` and
  `l2[r] = sum_c counts[r][c]^2` (collapsed forms of Go's
  `InsertWithHash`-maintained running norms for the unweighted
  unit-step stream the parity harness drives — the only producer
  pattern this wire path serves today). `sum_counts` / `sum2_counts`
  remain empty (Frequency-Only mode).
- `asap-precompute-rs/tests/cross_language_parity.rs`: drop the
  `#[ignore]` reason citing the pre-#45 hash-layer divergence.
- `integration/parity/golden_test.go`: switch the CMS fixture
  generator from `sk.SerializeProtoBytesFO()` to
  `sk.SerializePortableFO()` + strip `Producer` / `HashSpec` +
  `proto.Marshal` (matches the DDSketch / KLL / CountSketch pattern
  established by PRs #247 / #250 / #253).

## HLL fixture generator alignment

Discovered while regenerating fixtures end-to-end after the CMS work:
the HLL fixture generator was the odd one out — it called
`sk.SerializeProtoBytes()` directly (which embeds Producer +
HashSpec), while the Rust HLL wrapper sets both fields to `None`. PR
#252 un-ignored `hll_byte_parity_with_go` but did not touch
`golden_test.go`, so the regenerated fixture diverged from Rust by
exactly the 134-byte Producer + HashSpec metadata footprint. The test
only "passed" because fixtures are gitignored and developers rarely
regenerate-then-test in one step — once you do (`GOLDEN_REGEN=1 go
test ... && cargo test --include-ignored ...`), HLL fails.

- `integration/parity/golden_test.go`: HLL block now uses
  `sk.SerializePortable()` + strip `Producer` / `HashSpec` +
  `proto.Marshal`, matching DDSketch / KLL / CountSketch / CMS.

## Verification

- `GOLDEN_REGEN=1 go test -run TestGenerateGoldenFixtures
  ./integration/parity/...` — passes; HLL fixture goes from 16532 →
  16398 bytes (-134 = stripped Producer + HashSpec); CMS fixture is
  8275 bytes (Frequency-Only INT64 payload).
- `cargo test --release --test cross_language_parity -- --include-ignored`
  — 7/7 pass: ddsketch, kll, hll, countsketch, cms byte-parity tests
  + 2 sanity tests, no ignored remaining.
- `cargo test --release -p asap-precompute-rs` — full suite green
  (27 lib tests + 7 parity tests).

Closes #243.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol deleted the phase3/cross-parity-unignore-countsketch branch May 9, 2026 18:00
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