Skip to content

fix(perf-harness): close 4 gaps from Phase 2.11B deployment perf run - #249

Merged
zzylol merged 1 commit into
mainfrom
phase2/perf-harness-gap-fixes
May 5, 2026
Merged

zzylol merged 1 commit into
mainfrom
phase2/perf-harness-gap-fixes

Conversation

@zzylol

@zzylol zzylol commented May 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes the four harness gaps surfaced by Phase 2.11B (PR #238) so the
next operator running the deployment-perf audit gets real numbers in
every column instead of NaN, and so a 10% shim regression is visible
at the CPU level rather than buried in measurement noise.

Per-gap status

# Gap Resolution Where
1 Gateway metric-name skew (v0.108 → v0.141) FIX deploy/scripts/measure-baseline.py
2 Backend /metrics empty under ingest-only soak DOCUMENT docs/phase-2-perf-deployment.md "Gaps" #2
3 No per-observation latency histogram on shim FIX (DDSketch only) + follow-up asap-precompute-go/precompute.go, ddsketchprocessor/{monitor,processor,config_translate,shim_helpers}.go
4 Workload too quiet to discriminate 10% regression FIX deploy/docker-compose/baseline-b3-delta.yml

Gap 1 — gateway metric names

Each gateway query is now <v0.141 name> or <v0.108 name>:
otelcol_process_cpu_seconds_total or otelcol_process_cpu_seconds,
otelcol_process_memory_rss_bytes or otelcol_process_memory_rss,
and the analogous _total/no-suffix pair on
otelcol_receiver_accepted_metric_points and
otelcol_exporter_sent_metric_points. Today's stack (v0.141 on both
agent and gateway) populates the first variant; legacy worktree
replays still hit the second. NaN only when neither exists.

Gap 2 — backend /metrics

asap_ingest_samples_total and asap_query_duration_seconds_bucket
genuinely don't exist under ingest-only operation; closing the gap
needs either a PromQL replay path on the harness side or a synthetic
ingest counter on the backend. Both are out of scope for a
harness-fixes PR. Doc updated to call this out plus a docstring note
on the query templates themselves so the operator sees in-script why
the column is blank.

Gap 3 — per-observation latency histogram

Two-part fix:

  • Runtime (asap-precompute-go). Adds a LatencyObserver func(d time.Duration) hook installed via Precompute.SetLatencyObserver.
    The hook fires once per Observe call (success, ErrSeriesCapExceeded,
    ErrLateData, matcher-miss all count) so the histogram envelope
    matches what testing.B measured in Phase 2.11A. Stored in an
    atomic pointer so concurrent Observe calls see a coherent snapshot;
    hot-path cost when nil is one Load + nil-check.
  • DDSketch shim wiring. enableSelfMonitoring constructs a
    Float64Histogram named asap_processor_observe_seconds with
    bucket boundaries spanning 50 ns – 10 ms. Each per-metric
    Precompute spawned via getOrCreate picks up the histogram via
    proc.recordObserveLatency. Surfaces on the deployed /metrics
    endpoint when EnableSelfMonitoring=true (production default).

The other 4 shims (KLL, HLL, CountSketch, CountMin) stay backwards-
compatible — they don't call SetLatencyObserver and lose nothing.
Wiring those four is mechanical; deferred to Phase 2.11C to keep
this PR focused per the task scope constraint.

Test: TestPrecompute_LatencyObserver in precompute_test.go
exercises hook installation, fires-once-per-Observe semantics
(including post-Tick), and disable.

Gap 4 — saturating workload

baseline-b3-delta.yml now overrides EXPORTER_CARDINALITY=100000
and EXPORTER_FREQ_HZ=100 (both still env-shadowable), chosen to
land the agent in the 50–70% one-core band on the reference
Threadripper hardware. Numerical re-baselining of pre-shim vs
post-shim under the new profile is not in this PR — that's its
own measurement, tracked as Phase 2.11C "saturating-load
comparison".

Validation

cd asap-precompute-go && go test ./...
ok  github.com/ProjectASAP/asap-precompute-go
ok  github.com/ProjectASAP/asap-precompute-go/controlchannel
ok  github.com/ProjectASAP/asap-precompute-go/otel
ok  github.com/ProjectASAP/asap-precompute-go/sketches
ok  github.com/ProjectASAP/asap-precompute-go/telegraf

for p in ddsketch kll hll countsketch countminsketch; do
  cd opentelemetry-collector-contrib-patch/processor/${p}processor && go test ./...
done
ok  .../ddsketchprocessor
ok  .../kllprocessor
ok  .../hllprocessor
ok  .../countsketchprocessor
ok  .../countminsketchprocessor

cd integration/parity && go test -v ./...
ok  github.com/ProjectASAP/ASAPCollector/integration/parity

-race also passes on the new test (atomic-pointer LatencyObserver
slot exercised under concurrent Observe).

Test plan

  • go test ./... clean in asap-precompute-go
  • go test ./... clean in all 5 shim processors
  • go test -v ./... clean in integration/parity
  • python3 -c "import py_compile; py_compile.compile('deploy/scripts/measure-baseline.py')" clean
  • yaml.safe_load(open('deploy/docker-compose/baseline-b3-delta.yml')) clean
  • Re-run the b3-delta soak under the new saturating profile and
    record numbers in a Phase 2.11C doc — out of scope for this PR
    (harness-fixes only)
  • Wire the per-Observe histogram into the remaining 4 shims (KLL,
    HLL, CountSketch, CountMin) — Phase 2.11C follow-up

Follow-ups (deferred)

  • Phase 2.11C: histogram wiring on KLL/HLL/CountSketch/CountMin
    shims (mechanical copy of the DDSketch monitor.go diff).
  • Phase 2.11C: numerical re-comparison of pre-shim vs post-shim
    agent CPU under the saturating workload.
  • Standing: asap_sketch_payload_bytes_per_window counter (gap KLL Aggregator Implementation #4
    in the doc, untouched here — separate metric design).
  • Standing: deprecated EXPORTER_RATE reference in
    run-baseline-sweep.sh (gap KLL in otel-client #5 in the doc, untouched).
  • Standing: PromQL replay path so backend /metrics populates
    under ingest+query soak (gap CountMinSketch in opentelemetry-collector #2 design-level concern).

🤖 Generated with Claude Code

- measure-baseline.py: update gateway metric names from collector v0.108
  to v0.141.
- docs/phase-2-perf-deployment.md: document backend /metrics gap as
  design-level (separate concern from harness fixes).
- asap-precompute-go: add per-observation Prom histogram in runtime;
  shim wiring for at least DDSketch.
- baseline-b3-delta.yml: bump load profile to saturating workload
  for CPU regression discrimination.
@zzylol
zzylol merged commit eb825b7 into main May 5, 2026
@zzylol
zzylol deleted the phase2/perf-harness-gap-fixes branch May 5, 2026 01:45
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