feat: e2e SDK→Collector performance benchmark of window aggregation - #40
Merged
Merged
Conversation
Adds a systematic end-to-end benchmarking harness for all five sketch
types (DDSketch, KLL, CountSketch, CountMinSketch, HLL) running in
sdkSketch mode, plus a raw-gauge baseline for comparison.
New files:
- opentelemetry-app/cmd/e2esdkbench/main.go
Go benchmark program that measures the SDK process in isolation:
• Bandwidth: exact gRPC wire bytes via stats.Handler on the SDK
gRPC connection (OutPayload.WireLength)
• Memory: heap alloc + sys sampled every second via runtime.ReadMemStats
• CPU: user+sys process time via syscall.Getrusage delta
Supports sketch types: ddsketch|kll|countsketch|countminsketch|hll|baseline
Outputs per-second timeseries CSV and summary JSON per run.
- otel_collector_benchmark/bench_sdk_e2e.sh
Orchestration script: iterates sketch types × load rates, starts the
appropriate collector binary, monitors collector CPU/memory via ps,
drives e2esdkbench, and emits a combined aggregate CSV + report table.
- opentelemetry-collector-contrib-patch/cmd/nopcol/config-bench.yaml
Baseline collector config: OTLP receiver + nop processor + debug
exporter — no sketch computation anywhere.
Config fixes (grpc max message size):
- countsketchcol/config-batch.yaml: max_recv_msg_size_mib: 64
- countminsketchcol/config-batch.yaml: max_recv_msg_size_mib: 64
- hllcol/config-bench.yaml: max_recv_msg_size_mib: 64
CountSketch/CountMinSketch/HLL sketch payloads exceed the default
4 MiB gRPC message limit at high export rates; raised to 64 MiB on
both the SDK send side and collector receive side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Applying a View with Aggregation=nil to a Float64Gauge suppresses reporting for that instrument, causing the baseline to report 0 B/s bandwidth. Skip the View entirely for the baseline case so the gauge uses its natural LastValue aggregation and exports normally. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two fixes for the e2esdkbench bandwidth measurement: 1. Replace grpc.WithStatsHandler (unreliable for non-sketch metric types in the patched SDK — OutPayload.WireLength was 0 for ExplicitBucket- Histogram) with /proc/net/dev loopback TX byte delta. This counts all bytes written to the TCP socket during the run, regardless of gRPC internals, and works uniformly for baseline and all sketch types. 2. Baseline mode now uses AggregationExplicitBucketHistogram with an explicit view, matching the same export path as sketch types. This ensures the instrument is registered and exported, producing measurable bandwidth (~2.8 MB/s at 10k MPS vs ~866 KB/s for DDSketch at 10k MPS, as expected since buckets are larger than sketch serialization). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
Author
|
@GnaneshGnani FYI |
…ate parameterization) - Refactor e2esdkbench CLI: replace --workers/--hosts/--metrics/--interval with --series and --samples-per-sec-per-series for clearer throughput control - Update bench_sdk_e2e.sh to sweep 1000 series × 1/10/100/1000 samples/s/series - Add sketch aggregation types to opentelemetry-go-patch (DDSketch, KLL, CountSketch, CountMinSketch, HLL): aggregation.go, pipeline.go, aggregate.go, metricdata/data.go, OTLP exporter transform - Update opentelemetry-app go.mod to pull sketch deps (sketches-go, sketchlib-go) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
zzylol
force-pushed
the
9-performance-evaluation-of-e2e-otel
branch
from
March 17, 2026 17:17
8ac8f98 to
a02eece
Compare
- baseline: switch SDK from ExplicitBucketHistogram to Float64Gauge (LastValue) so raw samples are sent without aggregation - nopcol: replace debug exporter with true nop exporter and remove batch processor for a clean pass-through sink - all sketch types (ddsketch, kll, hll, countsketch, countminsketch): decouple readerInterval (1s) from workerInterval (1s/sps) so each exported sketch aggregates all samples in a 1-second window Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…regation - bench_sdk_e2e.sh: all sketch types now use config-window.yaml - countsketch: window_size 5s→10s, add max_recv_msg_size_mib: 64, remove batch processor and debug exporter - countminsketch: add max_recv_msg_size_mib: 64 (window config) - hll: add max_recv_msg_size_mib: 64, set drop_original: true (window config) - ddsketch/kll window configs already correct (window_duration: 10s) Note: CountSketch processor aggregates globally by metric name and host name (two shared sketches), not per individual series — this is a design limitation of the processor unrelated to this change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both have design limitations (countsketch: no per-series aggregation; countminsketch: dropped for scope reduction). Benchmark now covers baseline, ddsketch, kll, and hll only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Large log file should not be tracked in version control. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All sketch types and baseline now record via Float64Gauge. Sketch aggregation is applied via a view override (not by instrument type), so the instrument type no longer needs to differ between modes. Removes useHistogram flag and the Float64Histogram code path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Baseline reader interval = workerInterval (e.g. 20ms at 50 sps/s) so each raw gauge sample is exported individually. Sketch types keep the 1s reader interval so each sketch aggregates a full second of samples. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This reverts commit ba63a67.
5-panel overview (bandwidth, SDK CPU, SDK memory, collector memory, collector CPU) across all 4 sketch types × 4 rates (1K–1M MPS). Generated from aggregate_summary.csv (60s, 1000 series, window mode). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SieDeta
pushed a commit
that referenced
this pull request
Apr 17, 2026
…2e-otel feat: e2e SDK→Collector performance benchmark of window aggregation
4 tasks
zzylol
added a commit
that referenced
this pull request
May 5, 2026
…ugh wire_alpha() (#247) Pairs with asap_sketchlib PR #40, which aligns `asap_sketchlib::DdSketch::update`'s bucket-store growth with `sketchlib-go`'s `Buckets.ensure` (chunks of 128, half-chunk-centered seed) and adds a `wire_alpha()` accessor that returns the gamma-roundtripped alpha matching Go's `SerializePortable` output. This commit: - Updates `DDSketchWrapper::build_state` to populate the proto's `alpha` field via `self.sk.wire_alpha()` instead of `self.sk.alpha`, so the emitted `DDSketchState.alpha` bytes match Go's. Without the roundtrip, even with the chunked-128 store layout in place, the proto bytes still diverge on the very first field. - Removes the `#[ignore]` from `cross_language_parity::ddsketch_byte_parity_with_go`. With the upstream fix in place and the wrapper routing through `wire_alpha()`, `cargo test --test cross_language_parity ddsketch_byte_parity_with_go` now passes byte-equality against the `integration/parity/golden/ddsketch_envelope.bin` fixture. KLL / HLL / CountSketch / CMS parity tests remain `#[ignore]`'d — their divergences are tracked in the same upstream issue and will be addressed in subsequent asap_sketchlib PRs. Refs #243. 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.
Summary
This PR adds an end-to-end performance benchmark for the SDK→Collector pipeline across sketch types, and aligns the benchmark setup to reflect realistic aggregation behavior.
New files
opentelemetry-app/cmd/e2esdkbench/main.go: Go benchmark that drives the SDK under configurable load, measures bandwidth (loopback TX via/proc/net/dev), SDK heap/CPU (runtime.ReadMemStats+syscall.Getrusage), and writes per-second CSV + summary JSON per run.otel_collector_benchmark/bench_sdk_e2e.sh: Shell orchestration script — iterates sketch types and rates, starts/stops the appropriate collector binary, monitors collector CPU/memory viaps, and aggregates results intoaggregate_summary.csv.opentelemetry-collector-contrib-patch/cmd/nopcol/config-bench.yaml: Nop collector config for the baseline (OTLP receive → nop processor → nop exporter).SDK changes (
opentelemetry-go-patch)Noop()aggregate builder.pipeline.go(no logic change).Benchmark design
Sketch types in scope:
baseline,ddsketch,kll,hll(CountSketch and CountMinSketch dropped — CountSketch has no per-series aggregation support.)
Instruments: All modes use
Float64Gauge. Sketch types attach a view to override the defaultLastValueaggregation with the sketch aggregation. Baseline uses no view — the gauge's naturalLastValuesends one raw sample per series per export.SDK side:
1s / samples_per_sec_per_series(e.g. every 20ms at 50 sps/s).PeriodicReaderexports every 1 second, so each exported sketch aggregates all samples recorded in that window.PeriodicReaderexports at the worker rate (e.g. every 20ms), so every raw sample is sent individually with no aggregation.Collector side:
mode: windowwith a 10s tumbling window, aggregating per series across 10 consecutive SDK exports before flushing.nopcol: OTLP receive → nop processor → nop exporter (zero processing overhead).max_recv_msg_size_mib: 64on HLL collector for large per-series payloads at high rates.Collector config changes (
opentelemetry-collector-contrib-patch)bench_sdk_e2e.shnow useconfig-window.yaml.hllcol/config-window.yaml: addmax_recv_msg_size_mib: 64, setdrop_original: true.countsketchcol/config-window.yaml:window_size5s → 10s, addmax_recv_msg_size_mib: 64, removebatchprocessor anddebugexporter.countminsketchcol/config-window.yaml: addmax_recv_msg_size_mib: 64.nopcol/builder-config.yaml: replacedebugexporter/otlpexporterwithnopexporter.nopcol/config-bench.yaml: nop processor + nop exporter pipeline (no batch, no debug).Benchmark results
Config: 60s duration · 1,000 series · rates: 1K / 10K / 100K / 1M MPS · window mode (10s tumbling window)
SDK-side metrics
Collector-side metrics
Key observations
Test plan
nopcolbinary (BUILD_ALWAYS=1 ./bench_sdk_e2e.sh --sketch baseline)./bench_sdk_e2e.sh --sketch all --duration 60s --series 1000 --rates "1000 10000 100000 1000000"aggregate_summary.csvResourceExhaustederrors in collector logs🤖 Generated with Claude Code