feat(measure-baseline): producer-side CPU / RSS / bytes-out columns - #191
Merged
Merged
Conversation
The three-axis SDK sweeps (see docs/sdk-aggregation-three-axis-design.md,
paper §6.2c) need to measure what the SDK decision point costs at
the producer, independent of what the agent and backend do. The
current script only pulls agent / gateway / backend stats, so the
producer side — CPU spent building sketches, RSS held by the
raw-buffer, bytes actually leaving the fake-exporter container —
has been invisible.
Adds three columns, placed right after the workload labels so they
show up first in spreadsheets:
producer_cpu_cores docker stats CPUPerc / 100 on the
fake-exporter container.
producer_rss_mib docker stats MemUsage on same.
producer_bytes_out_per_s docker stats NetIO tx field, sampled
twice separated by --bytes-sample-window
(default 5s), divided by wall delta.
Implementation:
- docker_stats() now also parses the NetIO field, returning
cumulative tx/rx per container alongside CPU% and mem MiB.
- New docker_stats_with_bytes_rate(window_s) does the two-sample
dance in one call — reused for backend CPU/RSS so the sweep
only pays one 5s window per baseline iteration instead of
three trips through `docker stats`.
- Size-parser helpers split out for readability (kB / MB / GB /
KiB / MiB / GiB).
- --producer-container CLI flag so sweeps with renamed compose
projects can override the default
"docker-compose-fake-exporter-1".
Local smoke test on N=1 b0a-raw-stream with the three-axis
fake-exporter binary running at defaults:
producer_cpu_cores = 0.286
producer_rss_mib = 55.5
producer_bytes_out_per_s = 2506
(cAdvisor isn't in the compose stack — see
deploy/configs/prometheus.yml — so we can't pull these from
Prometheus directly. docker stats is the pragmatic source until
we add a cadvisor service, which is a larger compose change.)
Follow-up: §6.2a/b/c sub-sweeps at N=1 now have the measurement
infra they need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzylol
added a commit
that referenced
this pull request
Apr 23, 2026
New sweep driver that iterates the `(W, L, agg_type)` grid defined
in docs/sdk-aggregation-three-axis-design.md, bringing up the
compose stack once per cell, soaking, calling measure-baseline.py,
and tearing down.
Each of the paper's §6.2 sub-sweeps is a thin wrapper fixing two
axes and varying the third:
6.2a time: WINDOWS="1s 15s 60s 300s" PROJECTIONS=":" AGGS="dd-full"
6.2b label: WINDOWS="60s" PROJECTIONS=": zone,rack zone -"
AGGS="dd-full"
6.2c encoding: WINDOWS="60s" PROJECTIONS="zone,rack"
AGGS="raw-buffer dd-full dd-delta kll cms-full hll-full"
Implementation notes:
- PROJECTIONS uses ":" as a bash-friendly escape for "keep all
labels" (the natural empty-string would be awkward to pass
through a space-separated list) and "-" for "drop all".
decode_projection() maps those back to what
fake-exporter's EXPORTER_SDK_PROJECTION expects.
- Uses baseline-b0a-raw-stream.yml as a neutral agent shape
(OTLP → batch(1s) → OTLP), which keeps the agent from running
a sketch pipeline on top and conflating the SDK-side
measurement. The SDK axis is the one under study.
- Row tag is "w${W}-l${PROJ_RAW}-a${AGG}" so the resulting CSV
is trivially splittable back into the grid for plotting.
Smoke-tested locally against the PR #189/#190/#191 stack:
$ WINDOWS=5s PROJECTIONS=":" AGGS=raw-buffer SOAK_S=30 \
CARDINALITY=50 FREQ_HZ=5 BYTES_WIN=3 \
./deploy/scripts/run-three-axis-sweep.sh > /tmp/sweep.csv
baseline,scale,rate,cardinality,producer_cpu_cores,...
w5s-l:-araw-buffer,N1,,50,0.025,9.754,322.269,...
Driver brings up/down correctly, producer-side columns populate,
CSV is well-formed. Numeric validation of the aggregator output
(e.g., "does raw-buffer really emit every sample under gzip
compression?") belongs to the §6.2c sub-sweep PR that uses this
driver to collect actual data.
Stacked on feat/measure-baseline-producer-columns (#191) — that
PR adds the producer columns this script relies on.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzylol
added a commit
that referenced
this pull request
Apr 23, 2026
New sweep driver that iterates the `(W, L, agg_type)` grid defined
in docs/sdk-aggregation-three-axis-design.md, bringing up the
compose stack once per cell, soaking, calling measure-baseline.py,
and tearing down.
Each of the paper's §6.2 sub-sweeps is a thin wrapper fixing two
axes and varying the third:
6.2a time: WINDOWS="1s 15s 60s 300s" PROJECTIONS=":" AGGS="dd-full"
6.2b label: WINDOWS="60s" PROJECTIONS=": zone,rack zone -"
AGGS="dd-full"
6.2c encoding: WINDOWS="60s" PROJECTIONS="zone,rack"
AGGS="raw-buffer dd-full dd-delta kll cms-full hll-full"
Implementation notes:
- PROJECTIONS uses ":" as a bash-friendly escape for "keep all
labels" (the natural empty-string would be awkward to pass
through a space-separated list) and "-" for "drop all".
decode_projection() maps those back to what
fake-exporter's EXPORTER_SDK_PROJECTION expects.
- Uses baseline-b0a-raw-stream.yml as a neutral agent shape
(OTLP → batch(1s) → OTLP), which keeps the agent from running
a sketch pipeline on top and conflating the SDK-side
measurement. The SDK axis is the one under study.
- Row tag is "w${W}-l${PROJ_RAW}-a${AGG}" so the resulting CSV
is trivially splittable back into the grid for plotting.
Smoke-tested locally against the PR #189/#190/#191 stack:
$ WINDOWS=5s PROJECTIONS=":" AGGS=raw-buffer SOAK_S=30 \
CARDINALITY=50 FREQ_HZ=5 BYTES_WIN=3 \
./deploy/scripts/run-three-axis-sweep.sh > /tmp/sweep.csv
baseline,scale,rate,cardinality,producer_cpu_cores,...
w5s-l:-araw-buffer,N1,,50,0.025,9.754,322.269,...
Driver brings up/down correctly, producer-side columns populate,
CSV is well-formed. Numeric validation of the aggregator output
(e.g., "does raw-buffer really emit every sample under gzip
compression?") belongs to the §6.2c sub-sweep PR that uses this
driver to collect actual data.
Stacked on feat/measure-baseline-producer-columns (#191) — that
PR adds the producer columns this script relies on.
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
Measurement infra for the three-axis SDK sweep (see
docs/sdk-aggregation-three-axis-design.md, paper §6.2c). Without producer-side columns the sweep can tell you what the agent / gateway / backend see but not what the SDK decision actually costs the instrumented process — which is the whole point of the encoding ablation.Adds three columns (placed right after the workload labels so they show up first in spreadsheets):
producer_cpu_coresdocker statsCPUPerc / 100on the fake-exporter containerproducer_rss_mibdocker statsMemUsageon sameproducer_bytes_out_per_sdocker statsNetIOtx field, sampled twice separated by--bytes-sample-window(default 5s)Why
docker statsand not PrometheuscAdvisor isn't wired into
deploy/configs/prometheus.yml(only OTel targets are scraped), socontainer_network_transmit_bytes_totaldoesn't exist. Pulling fromdocker statsdirectly is the pragmatic source until someone wants to add a cadvisor service to the compose stack (a larger change I'm deferring).Implementation notes
docker_stats()now parses theNetIOfield — cumulative tx/rx per container.docker_stats_with_bytes_rate(window_s)does the two-sample dance in one call, reused for backend CPU/RSS so the sweep pays one--bytes-sample-windowpause per baseline instead of three separatedocker statstrips.--bytes-sample-windowdefault 5s. Too short (≤1s) and the tx counter barely moves; too long and every sweep iteration gets expensive.--producer-containerCLI flag so renamed compose projects can override the default.Test plan
Local smoke on a live N=1 b0a-raw-stream stack:
All three producer columns populate with sensible values.
Follow-up
§6.2a/b/c sub-sweeps at N=1 now have the measurement infra they need. That's the next PR.
🤖 Generated with Claude Code