feat: CMS/CS bandwidth optimisations — full-sketch Opt-1/2/3, delta packed-array encoding, adaptive transmission - #91
Merged
Conversation
…ne results The deltaaccbench tool called InsertValue/EstimateCardinality which don't exist in the local sketchlib-go HLL implementation; fix to use Insert/Estimate. Adds benchmark results doc (docs/benchmark-delta-vs-raw-baseline-2026-03-28.md) with full CPU, memory, and bandwidth numbers from a 20-window × 5 000-insert run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds RawBytes (8 B × inserts/window, proto-packed fixed64) to every windowResult and AvgRawBytes / RawVsFullRatio / RawVsDeltaRatio to sketchResult, so the table and CSV now show all three tiers: Raw B avg | Full B avg | Delta B avg | Full/Delta | Raw/Full | Raw/Delta Updates the benchmark results doc with the three-way comparison table and per-sketch interpretation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents four optimisations that together bring CMS/CS delta payloads
below the raw-sample baseline (~10 KB vs 40 KB for CMS, ~2–4 KB for CS):
Opt-1: omit sum_counts/sum2_counts (3× CMS reduction, unweighted streams)
Opt-2: sint64 packed varint instead of float64 (4–8×, schema already exists)
Opt-3: CS epsilon 0.01 → 0.02 config change (4× column reduction)
Opt-4: replace TopK heap with Space Saving key candidates —
covers weighted inserts, eliminates upstream CS query per insert,
downstream TopK built from globally-merged counts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Applies the four CMS/CS delta-payload optimisations designed in docs/cms-cs-delta-transmission-optimizations.md to the DataCollector pipeline. Depends on sketchlib-go PR ProjectASAP/sketchlib-go#45 (feat/cms-cs-payload-opts, commit b24e56e). ## Opt-1 + Opt-2 — CMS FrequencyOnly + sint64 varint opentelemetry-go-patch/sdk/metric/internal/aggregate/countminsketch.go: serializeCMSketch() → s.SerializeProtoBytesFO() (was: s.SerializeProtoBytes(); now: FrequencyOnly + sint64 encoding) opentelemetry-collector-contrib-patch/processor/countminsketchprocessor/processor.go: serializeCMS() → s.SerializeProtoBytesFO() Removes now-unused proto.Marshal import. Combined effect: CMS full/delta payloads drop from ~246 KB / ~150 KB per window to ~6–10 KB per window (Opt-1 saves 3×, Opt-2 saves 4–8×). ## Opt-3 — CS epsilon 0.01 → 0.02 All 9 YAML configs in opentelemetry-collector-contrib-patch/cmd/countsketchcol/ updated: epsilon: 0.01 → 0.02. Also updates opentelemetry-app configs. Effect: CS column count drops 16384 → 4096 (4× reduction), bringing CS delta payloads from ~88 KB to ~22 KB per window. ## Dependency — sketchlib-go pseudoversion bump All 22 go.mod files updated to sketchlib-go pseudoversion v0.0.0-20260328221809-b24e56e64e94 (commit b24e56e on feat/cms-cs-payload-opts). Local replace directives added to all go.mod files that were missing them so builds resolve via local /mydata/sketchlib-go without requiring module proxy access to the private GitHub repo. Design reference: docs/cms-cs-delta-transmission-optimizations.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the full 4-mode (raw-unbatched / raw-batched / full-sketch / delta-sketch)
transmission benchmark infrastructure and fixes two bugs found during the run.
Benchmark infra (bench_4modes.sh):
- Orchestrates SDK → Agent(:4317) → Backend nopcol(:4319) pipeline
- Measures SDK→Agent and Agent→Backend bandwidth separately via /proc/net/dev
and ss(8) bytes_sent
- Samples agent/backend CPU% and RSS every 1s; emits per-mode result.json
- Supports --sketch cms|cs|all, --duration, --series, --rate flags
- New agent configs: config-bench-{raw-unbatched,raw-batched,cms/cs-full,cms/cs-delta}.yaml
for countminsketchcol, countsketchcol, and nopcol
Bug fixes:
- processor/countminsketchprocessor: cloneCMS called DeserializeCountMinSketchFromBytes
(gob) on proto-serialized bytes → nil clone → nil-pointer panic on 2nd window.
Fix: use DeserializeCountMinSketchFromProtoBytes.
- opentelemetry-go-patch/hllsketch.go: InsertValue/EstimateCardinality renamed to
Insert/Estimate in current sketchlib-go HLL API.
Benchmark results (500 series × 10 sps, 60s, loopback):
CMS raw-unbatched SDK→Agent 287 KB/s Agent→Backend 23 KB/s AgentMem 191 MB
CMS raw-batched SDK→Agent 284 KB/s Agent→Backend 21 KB/s AgentMem 195 MB
CMS full sketch SDK→Agent 271 KB/s Agent→Backend 2.6 KB/s AgentMem 418 MB
CMS delta sketch SDK→Agent 270 KB/s Agent→Backend 1.5 KB/s AgentMem 752 MB
CS raw-unbatched SDK→Agent 287 KB/s Agent→Backend 23 KB/s AgentMem 43 MB
CS raw-batched SDK→Agent 284 KB/s Agent→Backend 21 KB/s AgentMem 50 MB
CS full sketch SDK→Agent 269 KB/s Agent→Backend 0.86 KB/s AgentMem 37 MB
CS delta sketch SDK→Agent 269 KB/s Agent→Backend 0.86 KB/s AgentMem 37 MB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SieDeta
pushed a commit
that referenced
this pull request
Apr 17, 2026
…acked-array encoding, adaptive transmission (#91) * bench: fix deltaaccbench HLL API mismatch and add delta-vs-raw baseline results The deltaaccbench tool called InsertValue/EstimateCardinality which don't exist in the local sketchlib-go HLL implementation; fix to use Insert/Estimate. Adds benchmark results doc (docs/benchmark-delta-vs-raw-baseline-2026-03-28.md) with full CPU, memory, and bandwidth numbers from a 20-window × 5 000-insert run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * bench: add raw-sample column to deltaaccbench (Raw vs Full vs Delta) Adds RawBytes (8 B × inserts/window, proto-packed fixed64) to every windowResult and AvgRawBytes / RawVsFullRatio / RawVsDeltaRatio to sketchResult, so the table and CSV now show all three tiers: Raw B avg | Full B avg | Delta B avg | Full/Delta | Raw/Full | Raw/Delta Updates the benchmark results doc with the three-way comparison table and per-sketch interpretation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: CMS/CS delta transmission optimisation design Documents four optimisations that together bring CMS/CS delta payloads below the raw-sample baseline (~10 KB vs 40 KB for CMS, ~2–4 KB for CS): Opt-1: omit sum_counts/sum2_counts (3× CMS reduction, unweighted streams) Opt-2: sint64 packed varint instead of float64 (4–8×, schema already exists) Opt-3: CS epsilon 0.01 → 0.02 config change (4× column reduction) Opt-4: replace TopK heap with Space Saving key candidates — covers weighted inserts, eliminates upstream CS query per insert, downstream TopK built from globally-merged counts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cms-cs): implement Opt-1/2/3 payload optimisations in DataCollector Applies the four CMS/CS delta-payload optimisations designed in docs/cms-cs-delta-transmission-optimizations.md to the DataCollector pipeline. Depends on sketchlib-go PR ProjectASAP/sketchlib-go#45 (feat/cms-cs-payload-opts, commit b24e56e). ## Opt-1 + Opt-2 — CMS FrequencyOnly + sint64 varint opentelemetry-go-patch/sdk/metric/internal/aggregate/countminsketch.go: serializeCMSketch() → s.SerializeProtoBytesFO() (was: s.SerializeProtoBytes(); now: FrequencyOnly + sint64 encoding) opentelemetry-collector-contrib-patch/processor/countminsketchprocessor/processor.go: serializeCMS() → s.SerializeProtoBytesFO() Removes now-unused proto.Marshal import. Combined effect: CMS full/delta payloads drop from ~246 KB / ~150 KB per window to ~6–10 KB per window (Opt-1 saves 3×, Opt-2 saves 4–8×). ## Opt-3 — CS epsilon 0.01 → 0.02 All 9 YAML configs in opentelemetry-collector-contrib-patch/cmd/countsketchcol/ updated: epsilon: 0.01 → 0.02. Also updates opentelemetry-app configs. Effect: CS column count drops 16384 → 4096 (4× reduction), bringing CS delta payloads from ~88 KB to ~22 KB per window. ## Dependency — sketchlib-go pseudoversion bump All 22 go.mod files updated to sketchlib-go pseudoversion v0.0.0-20260328221809-b24e56e64e94 (commit b24e56e on feat/cms-cs-payload-opts). Local replace directives added to all go.mod files that were missing them so builds resolve via local /mydata/sketchlib-go without requiring module proxy access to the private GitHub repo. Design reference: docs/cms-cs-delta-transmission-optimizations.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * bench: 4-mode real-OTel BW benchmark + fix CMS delta crash + fix HLL API Adds the full 4-mode (raw-unbatched / raw-batched / full-sketch / delta-sketch) transmission benchmark infrastructure and fixes two bugs found during the run. Benchmark infra (bench_4modes.sh): - Orchestrates SDK → Agent(:4317) → Backend nopcol(:4319) pipeline - Measures SDK→Agent and Agent→Backend bandwidth separately via /proc/net/dev and ss(8) bytes_sent - Samples agent/backend CPU% and RSS every 1s; emits per-mode result.json - Supports --sketch cms|cs|all, --duration, --series, --rate flags - New agent configs: config-bench-{raw-unbatched,raw-batched,cms/cs-full,cms/cs-delta}.yaml for countminsketchcol, countsketchcol, and nopcol Bug fixes: - processor/countminsketchprocessor: cloneCMS called DeserializeCountMinSketchFromBytes (gob) on proto-serialized bytes → nil clone → nil-pointer panic on 2nd window. Fix: use DeserializeCountMinSketchFromProtoBytes. - opentelemetry-go-patch/hllsketch.go: InsertValue/EstimateCardinality renamed to Insert/Estimate in current sketchlib-go HLL API. Benchmark results (500 series × 10 sps, 60s, loopback): CMS raw-unbatched SDK→Agent 287 KB/s Agent→Backend 23 KB/s AgentMem 191 MB CMS raw-batched SDK→Agent 284 KB/s Agent→Backend 21 KB/s AgentMem 195 MB CMS full sketch SDK→Agent 271 KB/s Agent→Backend 2.6 KB/s AgentMem 418 MB CMS delta sketch SDK→Agent 270 KB/s Agent→Backend 1.5 KB/s AgentMem 752 MB CS raw-unbatched SDK→Agent 287 KB/s Agent→Backend 23 KB/s AgentMem 43 MB CS raw-batched SDK→Agent 284 KB/s Agent→Backend 21 KB/s AgentMem 50 MB CS full sketch SDK→Agent 269 KB/s Agent→Backend 0.86 KB/s AgentMem 37 MB CS delta sketch SDK→Agent 269 KB/s Agent→Backend 0.86 KB/s AgentMem 37 MB Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
zzylol
added a commit
that referenced
this pull request
May 7, 2026
After backend PRs #91 / #92 / #93 land, this commit: 1. Migrates `deploy/configs/backend-storage-routing.yaml` to the v7 dual-routing schema. http_requests_total fans out to TWO targets — warm-tier default + cold-archive `[count, topk, rate_post_hoc]`. Freshness probes route via gorilla. 2. Patches `asap-gorilla::IndexEntry` + `IndexFile` to accept BOTH the backend-canonical and agent-side JSON shapes (the agent's `gorillas3processor` writes `object`/`start_ts_nano`/`point_count`; backend writes `key`/`time_range`/`sample_count`). 3 new tests. 3. Patches `deploy/scripts/measure_freshness.py` to filter NaN responses from gorilla on empty windows. Pre-v7 the int conversion blew up the script entirely; now we keep polling. 4. Patches `deploy/docker-compose/base.yml` to make backend `RUST_LOG` env-overridable via `BACKEND_RUST_LOG`. 5. Patches `gorillas3processor.encoder.go` to write the seriesCount slot at byte offset 9 (post-magic, post-version) instead of the buggy offset 5. Pre-v7 every chunk landed with corrupted header bytes — invisible because no consumer decoded them; v7's `last_over_time` query path is the first that does. 6. Includes the v7 demo run artifacts under `deploy/eval-results/mvp-v7-2026-05-06/` plus an annotated `MVP_REPORT_v7.md` with v6.1 → v7 verdict diff and the diagnosis chain explaining why ④ and ⑥ remain UNKNOWN despite the routing side closing fully (agent encoder rebuild + SimpleEngine raw counter support are deferred next steps). The agent encoder fix is staged as a code-level commit; it takes effect only after rebuilding `asap/sketchcol:dev` from the patched go binary, which requires the local OCB build chain. That rebuild is out of v7's two-change scope. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks
zzylol
added a commit
that referenced
this pull request
May 7, 2026
The original 3-phase plan (always-archive at gateway / delete JSONL / PromQL completeness) is partially superseded by what shipped via v5/v7. Updated to reflect what's already on main and what genuinely remains: - "Always-archive at gateway" effectively shipped via dual-routing (PR #91): BackendStorageRouting now allows multi-target per metric - The archive-tier engine has gained postings filtering (PR #295), partial-S3 reads (PR #295), concat-only compactor (PR #295), and freshness-pattern registration (PR #91) Two outstanding items remain: - Delete the JSONL cold-fallback (now safely unreachable under normal routing) - PromQL completeness on GorillaQueryEngine (Path A: vendor prometheus/promql via sidecar; Path B: pure-Rust evaluator; Path C: curated subset extension) Adds a "what's already on main" diff table at the top so reviewers immediately see what's done vs. what's outstanding. Adds a sentence about Prometheus-block-compatible layout potentially letting Thanos store-gateway answer queries directly (cross-references the comparison doc). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
3 tasks
zzylol
added a commit
that referenced
this pull request
May 7, 2026
… on GorillaQueryEngine (#292) * docs: design for JSONL deprecation + always-archive Gorilla-S3 + PromQL completeness Three-phase proposal to collapse ASAP's cold-fallback tier (JSONL) into the Gorilla-S3 archive tier: - Phase 1: always-archive every metric at the gateway (mirrors Databricks' Hydra always-streaming pattern); ~1-2 days - Phase 2: delete the JSONL path (LocalFsColdStore, parse_jsonl, raw-tee exporter, StorageBackend::ColdJsonlFallback enum variant, paper §Cold- fallback tier prose, cost-model "cold-tier scan bytes" line item); ~1-2 days - Phase 3: PromQL completeness on GorillaQueryEngine. Three sub-paths: Path A (vendor Prometheus' promql package, ~2 weeks, recommended for correctness), Path B (pure-Rust evaluator, ~4-6 weeks, correctness risk), Path C (extend curated subset, ~1 week, ships fast but reviewers may push back). Recommends Phase 1+2 combined for paper deadline (drops cold-fallback prose); Phase 3 ships as Path C bridge with Path A as post-deadline follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: rewrite to reflect post-v7 state The original 3-phase plan (always-archive at gateway / delete JSONL / PromQL completeness) is partially superseded by what shipped via v5/v7. Updated to reflect what's already on main and what genuinely remains: - "Always-archive at gateway" effectively shipped via dual-routing (PR #91): BackendStorageRouting now allows multi-target per metric - The archive-tier engine has gained postings filtering (PR #295), partial-S3 reads (PR #295), concat-only compactor (PR #295), and freshness-pattern registration (PR #91) Two outstanding items remain: - Delete the JSONL cold-fallback (now safely unreachable under normal routing) - PromQL completeness on GorillaQueryEngine (Path A: vendor prometheus/promql via sidecar; Path B: pure-Rust evaluator; Path C: curated subset extension) Adds a "what's already on main" diff table at the top so reviewers immediately see what's done vs. what's outstanding. Adds a sentence about Prometheus-block-compatible layout potentially letting Thanos store-gateway answer queries directly (cross-references the comparison doc). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
CMS and CS full-sketch payloads were larger than raw samples before this PR. Even delta transmission made it worse — delta cells used fixed 64-bit floats, so a sparse delta could cost more than a full sketch:
Workload:
deltaaccbench— 20 windows × 5 000 inserts, Zipf s=1.10, threshold=1.0. Raw baseline = 5 000 × 8 B uint64 hashes = 40 000 B/window.Root causes and full analysis:
docs/cms-cs-delta-transmission-optimizations.mdWhat was implemented
Six independent optimisations, applied in three layers:
Layer 1 — Full-sketch payload (sketchlib-go#45, DataCollector)
SerializePortableFO()— omitsum_counts/sum2_countsfrom CMS full payload; receiver reconstructsSum = Sum2 = Countfor unweighted streams (3× fewer arrays)CountMinSketch/portable.gocounts_int sint64(packed zigzag varint) replacescounts_float doublefor both CMS and CS; Zipf cells average 1–2 B instead of 8 BCountMinSketch/portable.go,CountSketch/portable.goepsilon: 0.01 → 0.02— halves the error bound relative to raw while reducing the matrix 4× (16 384 → 4 096 columns)cmd/countsketchcol/Layer 2 — Delta-cell encoding (sketchlib-go@019e21e, DataCollector)
repeated CountMinCell/repeated CountSketchCellproto messages with three parallel packed arrays (cell_rows uint32,cell_cols uint32,d_counts sint64); dropsd_sum/d_sum2from CMS delta cells (same reconstruction as Opt-1). Per-cell cost: 35 B → 4 B for CMS, 17 B → 4 B for CS. Backward-compat: oldcells_legacyfield retained for reading old producers.proto/countminsketch/,proto/countsketch/,*/delta_codec.go,*/delta.goLayer 3 — Adaptive transmission (DataCollector)
processor/countminsketchprocessor/processor.go,processor/countsketchprocessor/processor.goOther changes
SpaceSavingtracker replacesTopKHeap.UpdateCS; delta sendshh_keys(key strings only, no stale counts); downstream queries merged matrix for accurate globally-merged estimates. O(k) per insert → O(log k).cloneCMSDeserializeCountMinSketchFromBytes(gob) on proto bytes → nil clone → nil-pointer panic on 2nd windowInsertValue→Insert,EstimateCardinality→Estimate(sketchlib-go API rename)019e21e25cce+ local replace directives in all 22go.modfilesResults
deltaaccbench — before vs after (20 windows × 5 000 inserts, Zipf s=1.10, threshold=1.0)
All sketches after optimisation:
Accuracy measured by
deltaaccbench: mean and max relative query error vs ground truth over 20 windows. Accuracy is a property of the sketch algorithm and dimensions, not of the transmission encoding.CPU & memory overhead — delta=on vs delta=off (deltaaccbench)
Real-OTel deployment — bench_4modes.sh (500 series × 10 sps, 60 s run)
OTel SDK → Agent Collector (:4317) → Backend nopcol (:4319). SDK→Agent bandwidth is identical across all modes (~270–287 KB/s) — the optimisation is entirely in the agent→backend hop.
Bandwidth
CPU & memory
Key takeaways:
CS TopK: Space Saving vs prior heap
UpdateCS)+1— ignores weight+= w— correct for any weightmin + wTest plan
go build ./cmd/deltaaccbenchpasses (sketchlib-go@019e21e)go run ./cmd/deltaaccbench --windows=20 --inserts=5000pre-opt baseline reproducedgo run ./cmd/deltaaccbench --windows=20 --inserts=5000post-opt retest (2026-03-30)go test ./sketches/CountSketch/... ./sketches/CountMinSketch/... ./sketches/SpaceSaving/...passcmd/countminsketchcol/distbinary builds cleancmd/countsketchcol/distbinary builds cleanbench_4modes.sh --sketch cms --duration 60scompletes (4 modes × CMS)bench_4modes.sh --sketch cs --duration 60scompletes (4 modes × CS)🤖 Generated with Claude Code