Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ signals a backwards-compatible change.
as an empty window like any other, and that window takes a place in
`max_windows`.

### Removed

- **Count Sketch's proto and portable formats.** Count Sketch (`Count`)
serializes as ASAPv1 only (`serialize_to_bytes` / `deserialize_from_bytes`,
kind `0x04 0x00`). Removed: the portable `CountSketch`, `CountSketchDelta`
and `COUNT_SKETCH_TOPK_CAPACITY` (module
`message_pack_format::portable::countsketch` and their crate-root
re-exports), including `CountSketch`'s proto and MessagePack delta codecs
(`compute_delta`, `apply_delta_bytes`, `compute_delta_msgpack`,
`apply_delta_msgpack_bytes`); the `MessagePackCodec` impl for `Count`
(module `message_pack_format::native::countsketch`); the proto messages
`CountSketchDelta` and `CountSketchCell`; and `SketchEnvelope`'s
`count_sketch` field (11, now reserved). `CountSketchState` stays, as
UnivMon and Hydra embed it.

### Fixed

- `KLLDynamic` panicked on every quantile query once a NaN had entered the
Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ MessagePack (`rmp-serde`) support. **serde support** means the type derives `Ser
| EHSketchList | Yes | Yes |
| ExponentialHistogram | No | Yes |

Protobuf (prost): `.proto` definitions exist for CountMin, Count, HLL, DDSketch, KLL, Elastic, Coco, Hydra, and UnivMon. Rust conversion code is in progress.
Protobuf (prost): `.proto` definitions exist for CountMin, HLL, DDSketch, KLL, Elastic, Coco, Hydra, and UnivMon; Count Sketch has only the `CountSketchState` that Hydra and UnivMon embed. Rust conversion code is in progress.

### API Stability

Expand Down
4 changes: 2 additions & 2 deletions docs/message_pack_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ being **phased out** in favor of the per-sketch `wire.rs` + the shared
`envelope.rs`.

- `portable/` holds per-sketch wire types that predate the envelope. They
carry their own byte-parity goldens against `sketchlib-go` — HLL, Count-Min,
Count Sketch and KLL (both directions) — separate from `asapv1_golden/`.
carry their own byte-parity goldens against `sketchlib-go` — HLL, Count-Min
and KLL (both directions) — separate from `asapv1_golden/`.
- `native/` is a set of thin `MessagePackCodec` shims over the sketches'
`serialize_to_bytes` / `deserialize_from_bytes`. Every type it wraps emits the
ASAPv1 envelope, so each shim is a pass-through.
Expand Down
34 changes: 4 additions & 30 deletions docs/tests.md

Large diffs are not rendered by default.

10 changes: 4 additions & 6 deletions proto/countminsketch/countminsketch.proto
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,9 @@ message CountMinState {
// byte-identical delta frames for identical window state (cross-language byte
// parity).
//
// CountMinDelta is structurally identical to CountSketchDelta: rows, cols, the
// packed cell encoding, per-row norm deltas, and an optional repeated hh_keys
// at the SAME tag number (6). Both sketches can track heavy hitters; whether
// hh_keys is populated is a control-plane decision (it is empty/omitted when
// CountMinDelta carries rows, cols, the packed cell encoding, per-row norm
// deltas, and an optional repeated hh_keys (tag 6). Whether hh_keys is
// populated is a control-plane decision (it is empty/omitted when
// heavy-hitter tracking is not enabled for this sketch).
message CountMinDelta {
uint32 rows = 1;
Expand All @@ -92,8 +91,7 @@ message CountMinDelta {
repeated double l1 = 4 [packed = true];
// Per-row L2 norm deltas, length = rows.
repeated double l2 = 5 [packed = true];
// Heavy-hitter candidate keys from an upstream tracker, mirroring
// CountSketchDelta.hh_keys (same tag number 6, same wire shape). Downstream
// Heavy-hitter candidate keys from an upstream tracker. Downstream
// queries the merged Count-Min matrix for each key to (re)build its Top-K
// with globally-merged estimates. Empty/omitted when heavy-hitter tracking
// is not enabled.
Expand Down
53 changes: 2 additions & 51 deletions proto/countsketch/countsketch.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// countsketch.proto — Portable wire format for Count Sketch state.
// Also contains TopKState and HeapEntry used by CountSketch and UnivMon.
// countsketch.proto — CountSketchState, TopKState and HeapEntry, the
// messages UnivMon and Hydra embed.

syntax = "proto3";

Expand Down Expand Up @@ -72,52 +72,3 @@ message HeapEntry {

reserved 3; // Reserved for bytes_key alternative.
}

// ============================================================================
// Count Sketch Delta
// ============================================================================

// CountSketchDelta carries only the matrix cells that changed by at least the
// threshold between two consecutive snapshots, plus the full per-row L2 norm
// deltas and any heavy-hitter candidate keys.
//
// Cells apply additively on the receiver: matrix[row][col] += d_count. Count
// Sketch counters are signed (±1 increments), so d_count is a signed integer
// (sint64). Heavy-hitter candidate keys (hh_keys) are re-queried against the
// merged matrix downstream to rebuild the receiver's Top-K with accurate,
// globally-merged estimates.
//
// The packed cell encoding (cell_rows / cell_cols / d_counts, tags 9-11) plus
// l2 (tag 12) is the canonical form; the legacy per-cell message (tag 3),
// l2_legacy (tag 4) and topk (tag 5) are retained only so payloads from older
// producers still decode. This message is byte-identical to the Go reference
// implementation's CountSketchDelta so the two runtimes emit byte-identical
// delta frames for identical window state (cross-language byte parity).
message CountSketchDelta {
uint32 rows = 1;
uint32 cols = 2;
// Deprecated: use cell_rows/cell_cols/d_counts (tags 9-11). Retained for
// backward-compatible decode of payloads from older producers.
repeated CountSketchCell cells_legacy = 3;
// Deprecated: use l2 (tag 12) instead.
repeated double l2_legacy = 4 [packed = true];
// Deprecated: use hh_keys (tag 6) instead.
TopKState topk = 5;
// Heavy-hitter candidate keys from the upstream tracker. Downstream queries
// the merged Count Sketch matrix for each key to build its Top-K.
repeated string hh_keys = 6;
// Packed cell encoding (canonical form):
repeated uint32 cell_rows = 9 [packed = true]; // row index of each changed cell
repeated uint32 cell_cols = 10 [packed = true]; // col index of each changed cell
repeated sint64 d_counts = 11 [packed = true]; // signed integer count delta
repeated double l2 = 12 [packed = true]; // per-row L2 norm deltas
}

// CountSketchCell is the deprecated per-cell delta record. Producers emit the
// packed cell arrays on CountSketchDelta instead; this message exists only to
// decode payloads from older producers.
message CountSketchCell {
uint32 row = 1;
uint32 col = 2;
double d_count = 3; // deprecated: use CountSketchDelta.d_counts
}
3 changes: 2 additions & 1 deletion proto/sketchlib.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ message SketchEnvelope {
// The sketch payload. Exactly one field must be set.
oneof sketch_state {
CountMinState count_min = 10;
CountSketchState count_sketch = 11;
HyperLogLogState hll = 12;
KLLState kll = 13;
DDSketchState ddsketch = 14;
Expand All @@ -77,6 +76,8 @@ message SketchEnvelope {
ElasticState elastic = 18;
}

reserved 11;
reserved "count_sketch";
reserved 19 to 31; // Reserved for future sketch types.

// Geometric / NitroSketch sampling probability for the producing sketch.
Expand Down
8 changes: 2 additions & 6 deletions src/common/hashspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
//! ±1 signs.
//!
//! This module re-exposes that pipeline as a small, byte-key API so
//! sketches that consume keys as raw bytes (e.g. the wire-format
//! `CountSketch::update`) can match Go's emitted matrix
//! sketches that consume keys as raw bytes can match Go's emitted matrix
//! cell-for-cell. CountMinSketch's pending byte-parity fix will reuse
//! the same primitives — the seed table, derive_index, and derive_sign
//! are agnostic to whether ±1 signing is applied.
Expand Down Expand Up @@ -75,10 +74,7 @@ pub const CANONICAL_HASH_SEED: usize = 5;
/// derivation strategy so consumers can validate hash compatibility
/// before merging.
///
/// `asap_sketchlib`'s wire-format CountSketch constructs a
/// `HashSpec::default()` and feeds it to [`derive_index`] /
/// [`derive_sign`] on the hot path. The default matches Go's
/// `portableHashSpec()`:
/// The default matches Go's `portableHashSpec()`:
///
/// - `seed_list = CANONICAL_HASH_SEED_TABLE`
/// - `canonical_seed_index = CANONICAL_HASH_SEED` (= 5)
Expand Down
5 changes: 1 addition & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! UnivMon, tumbling windows, and batch/parallel execution helpers.
//! - [`message_pack_format`]: MessagePack/proto wire format shared with
//! `sketchlib-go`. Owns the wire-DTO sketch types consumed by the ASAP
//! query engine (`CountMinSketch`, `CountSketch`, `KllSketch`, `HllSketch`,
//! query engine (`CountMinSketch`, `KllSketch`, `HllSketch`,
//! `DdSketch`, `HydraKllSketch`, `CountMinSketchWithHeap`,
//! `SetAggregator`, `DeltaResult`).
//!
Expand Down Expand Up @@ -43,9 +43,6 @@ pub use common::*;
pub use message_pack_format::MessagePackCodec;
pub use message_pack_format::portable::countminsketch::{CountMinSketch, CountMinSketchDelta};
pub use message_pack_format::portable::countminsketch_topk::{CmsHeapItem, CountMinSketchWithHeap};
pub use message_pack_format::portable::countsketch::{
COUNT_SKETCH_TOPK_CAPACITY, CountSketch, CountSketchDelta,
};
pub use message_pack_format::portable::countsketch_topk::{CountSketchWithHeap, CsHeapItem};
pub use message_pack_format::portable::ddsketch::{DDSKETCH_GROW_CHUNK, DdSketch, DdSketchDelta};
pub use message_pack_format::portable::delta_set_aggregator::DeltaResult;
Expand Down
32 changes: 0 additions & 32 deletions src/message_pack_format/native/countsketch.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/message_pack_format/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
//! specifies the format `sketchlib-go` mirrors.

pub mod countminsketch;
pub mod countsketch;
pub mod countsketch_topk;
pub mod ddsketch;
pub mod hll;
Expand Down
24 changes: 10 additions & 14 deletions src/message_pack_format/portable/countminsketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,8 @@ pub fn sketchlib_cms_query(inner: &SketchlibCms, key: &str) -> f64 {
/// L1 and L2 norm deltas are carried for downstream error-accounting
/// but are not consumed by `apply_delta` itself.
///
/// Structurally identical to [`super::countsketch::CountSketchDelta`]: the
/// optional `hh_keys` channel carries heavy-hitter candidate keys forwarded by
/// an upstream tracker. Count-Min can track heavy hitters, but whether
/// The optional `hh_keys` channel carries heavy-hitter candidate keys
/// forwarded by an upstream tracker. Count-Min can track heavy hitters, but whether
/// `hh_keys` is populated is a control-plane decision — it is empty when
/// heavy-hitter tracking is not enabled. The receiver re-queries the merged
/// matrix for each key to (re)build its Top-K. Mirrors the Go reference
Expand Down Expand Up @@ -266,9 +265,8 @@ impl CountMinSketch {
/// Go producer maintains incrementally. Heavy-hitter candidate keys
/// (`hh_keys`) are sourced from an upstream tracker that this minimal
/// wrapper does not maintain, so the field is left empty (an empty repeated
/// field encodes to nothing on the wire), exactly as CountSketch's
/// `compute_delta` does. The returned bytes are a `prost`-encoded
/// [`crate::proto::sketchlib::CountMinDelta`], byte-identical to the Go
/// field encodes to nothing on the wire). The returned bytes are a
/// `prost`-encoded [`crate::proto::sketchlib::CountMinDelta`], byte-identical to the Go
/// `proto.Marshal(CountMinDelta)` output for the same inputs when no
/// heavy-hitter keys are forwarded (cross-language byte parity).
///
Expand Down Expand Up @@ -334,7 +332,7 @@ impl CountMinSketch {
l1,
l2,
// Heavy-hitter keys are control-plane-gated; this wrapper has no
// tracker, so the field is empty (mirrors CountSketch::compute_delta).
// tracker, so the field is empty.
hh_keys: Vec::new(),
cell_rows,
cell_cols,
Expand All @@ -348,9 +346,9 @@ impl CountMinSketch {
/// Go reference implementation's `DeserializeDelta` + `ApplyDelta`.
/// Reads the packed cell arrays (`cell_rows`/`cell_cols`/`d_counts`)
/// and falls back to the legacy per-cell records for payloads from
/// older producers. Heavy-hitter keys (`hh_keys`) are read symmetrically
/// (mirroring CountSketch) and carried onto the decoded delta; a plain CMS
/// keeps no Top-K, so they are not otherwise consumed here.
/// older producers. Heavy-hitter keys (`hh_keys`) are read and carried
/// onto the decoded delta; a plain CMS keeps no Top-K, so they are not
/// otherwise consumed here.
///
/// Returns `Err` if `bytes` is not a valid `CountMinDelta` proto or a
/// cell is out of range for this sketch's dimensions.
Expand Down Expand Up @@ -383,10 +381,8 @@ impl CountMinSketch {
cells,
l1: proto.l1,
l2: proto.l2,
// Heavy-hitter keys are carried through symmetrically (mirrors
// CountSketch). This wrapper keeps no Top-K, so they are not
// otherwise consumed; a control-plane sink would re-query the
// merged matrix for each key. Empty for a plain CMS.
// This wrapper keeps no Top-K, so heavy-hitter keys are carried
// through but not otherwise consumed. Empty for a plain CMS.
hh_keys: proto.hh_keys,
};
self.apply_delta(&delta)
Expand Down
Loading
Loading