Skip to content

feat(asap-tools): pooled and dashboard-style random workloads on ASAPQuery's RQE frontend - #909

Open
milindsrivastava1997 wants to merge 30 commits into
mainfrom
codex/random-pooled
Open

milindsrivastava1997 wants to merge 30 commits into
mainfrom
codex/random-pooled

Conversation

@milindsrivastava1997

Copy link
Copy Markdown
Contributor

Stacked on #907 (batch driver, collation and plots, time-ordered raw ClickHouse, dashboards K, Alibaba replay, x2 variant). It merges main for the RQE stack (#887–890). Review the commits from 556e2cd on; the earlier ones are #907's.

Summary

  • Pooled random workloads (random_workloads.py --pooled, set seed-862-pooled): the same random choices as the base set.
    • Quantiles are pooled: one quantile over all of a group's samples.
    • Sum top-k becomes topk(k, sum by (region, service, job) (...)).
    • PromQL can't express a pooled quantile, so Prometheus/VictoriaMetrics run the stand-in quantile by (G) (phi, quantile_over_time(phi, data[W])).
    • ClickHouse (raw and MV) computes the pooled quantile exactly from the RQE.
  • Dashboard-style workloads (--dashboard, set seed-862-dashboard, the final eval template). Ten pooled queries per workload:
    • a sum roll-up chain at every grouping;
    • a p50/p90/p99 panel by one grouping;
    • pooled quantiles at the other two groupings;
    • pooled top-k by service and by microservice.
    • Windows run from 1 s to 20 m. No 1 s sums: PromQL's closed window counts one more edge sample. No 1 s quantiles by microservice: below the accuracy curves' 1,000 samples.
  • ASAPQuery on its RQE frontend: a pooled workload's e2e config sets query_engine.frontend=rqe with a side file mapping each query's text to its tree (e2e.rqe_exprs.json). Prometheus runs the text. sketch_bench_e2e_configs.py reads a tree-only query's text from client_promql.
  • Validity (collate_batch.py): in a pooled or dashboard set, quantiles are checked against raw ClickHouse's exact pooled answers. Prometheus/VictoriaMetrics stand-ins are left unchecked.
  • Batch driver: the Prometheus arm forces query_engine.frontend=promql, since its config's sketchdb mode reads trees.
  • Frozen sets with saved plans (expr-only, from eval: export pooled quantiles and top-k from random manifests sketch-bench#230): seed-862-pooled and seed-862-dashboard, 10 workloads each.

Results so far (pooled w01, synthetic, all 5 systems valid)

System CPU-s Peak mem p95
ASAPQuery 1,296 0.35 GiB 0.05 s
ClickHouse+MV 1,868 2.64 GiB 0.30 s
raw ClickHouse 7,262 1.97 GiB 1.21 s
VictoriaMetrics 10,462 1.73 GiB 1.59 s
Prometheus 12,663 1.97 GiB 3.89 s

The PromQL stand-in is 11–304% off the exact pooled quantile; ASAPQuery's pooled DDSketch is about 5% off.

Validation

  • python3 -m unittest discover -s tests -p "test_*.py" in asap-tools/experiments: 269 pass. New tests cover:
    • pooled manifests pairing with base;
    • pooled quantile and top-k SQL;
    • the dashboard template's rules;
    • pooled pilot configs (RQE frontend, side file, VictoriaMetrics without it);
    • checked-query filtering;
    • the Prometheus arm's frontend override.
  • The prometheus-client tests pass (33). The merge with main resolved a conflict in main_prometheus_client.py: the RQE protocol and the pool size are both kept.
  • Re-collating base-final-1015 under the new checks gives the same 50 valid runs and ratios.

🤖 Generated with Claude Code

https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB

milindsrivastava1997 and others added 30 commits October 15, 2026 01:29
random_workload_batch.py runs every arm of the given workload sets on a
cluster, one job per two-node slot, longest first; cleans a slot's nodes
before each job, retries a failed job once under a new name, writes a
compare_arms summary per workload (ClickHouse+MV as the reference), and
keeps its state on disk so a restarted driver resumes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On resume, a job whose run is still alive is left alone (orphaned)
instead of rerun, and --skip-slots keeps the driver off busy nodes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
collate_batch.py writes one row per (set, workload, arm): CPU, memory,
latency p50/p95/sum, failed queries, the feeder's ingest lag, and whether
the run is valid (no failed queries, answers agreeing with Prometheus).
It reports each baseline's ratio to ASAPQuery over valid pairs.
plot_cost_latency.py draws p95 latency against total CPU per set, invalid
runs hollow. compare_arms now reports failed queries instead of crashing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… each scatter

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…chosen arms

The raw table's label-first order made every query read the whole table.
The batch driver can rerun some arms under a name tag and from a config
variant directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It cleaned and reused them, wrecking the runs still going there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cost-latency plot

Also a figure title, thicker axes, and "total compute cost" on the y axis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
random_workload_artifacts.py --dashboards K writes <workload>-dashK/ run
configs with every query group repeated K times (e2e, VictoriaMetrics,
ClickHouse and ClickHouse+MV), on the same plan, feeder and data. Each copy
is its own client group and thread, so copies are issued concurrently and
their latencies recorded apart.

The query client's connection pool now fits every query in flight; the
default 10 would open a new connection per excess request at K >= 2.
collate_batch.py collates batches of an arm subset, against ClickHouse+MV
when Prometheus didn't run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A workload table's gauge can carry recorded values (values.replay), which the
feeder loops one step per sample in place of generated ones. make_replay.py
fits Alibaba v2022 pod CPU into the random workloads' label shape and writes
such a table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Panel subtitles drop the workload set name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…etheus and ClickHouse

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… first

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Frozen for seed 862 with saved plans for all ten workloads, for a
cardinality point between base and x5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
--pooled keeps a workload's random choices and makes its quantiles pooled
(one over each group's samples; the PromQL stays the avg-of-series stand-in)
and its sum top-k rank the fine grouping's groups. ClickHouse SQL renders
both from the RQE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
…tend

seed-862-pooled freezes the pooled variant of the ten workloads with saved
plans (expr-only, from sketch-bench eval/random-pooled e2fb479). Their pilot
configs send ASAPQuery each query's tree (side file e2e.rqe_exprs.json) while
Prometheus runs the PromQL; the e2e config writer reads a tree-only query's
text from client_promql.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
Prometheus and VictoriaMetrics answer a pooled quantile with the
avg-of-series stand-in, so those queries are left unchecked for them and the
other arms' are checked against raw ClickHouse's exact pooled quantiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
…quantiles

Prometheus and VictoriaMetrics now run quantile by (G) (phi,
quantile_over_time(phi, data[100s])), which keeps the tail the pooled
quantile reads. Eval tables re-exported (sketch-bench eval/random-pooled);
the tree-only plans are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
--dashboard draws ten pooled queries per workload: a sum roll-up chain at
every grouping, a p50/p90/p99 panel, pooled quantiles at the other
groupings and pooled top-k by service and by microservice, over windows of
1 s to 20 m. seed-862-dashboard freezes ten, with saved plans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
…of the dashboard template

seed-862-half freezes the 5,000-series variant with saved plans. The
half and x2 dashboard sets freeze workload-01 with its plan, for a
cardinality sweep at 5k, 10k and 20k series.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
…uarantee

The plans' DDSketch (alpha 0.1) bounds relative error at 10%; the 5% check
failed answers by a hair that the plan promised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
A 1 s top-k window rendered as [0m], which Prometheus rejects. Dashboard
workloads 03, 05 and 07 re-frozen and re-exported; their plans are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KzRxtgjFfFJeyDy8fN2CB
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