Repository navigation
rqe-optimizer: read sketch accuracy from saturation curves - #171
Conversation
Code vs. the proposed saturation logic (to resolve)Proposed logic, for each (RAQE, deployment) pair:
Where the code matches
Where the code differs
Ambiguous
|
Resolution
Still open: the ambiguous case, a saturating point with the lookback's item count < the saturation point. The code currently reads the curve's (not yet stable) value at the lookback's item count rather than rejecting the deployment. |
|
On Where the code differs, 1 (no merge, x = T): I think this comes from the cost export and the saturation study being keyed differently, not from two genuinely different numbers. They should be one lookup. The data already lines up.
Proposal:
With this, x = T needs no special case. Where the workload looks like the cost-table measurement, the curve at n(T) is the cost-table value, and the check enforces that. Not covered:
|
Sketch accuracy now comes from the saturation study's error-vs-N curves, read at the items a deployment's answer covers per group, at the metric's fitted data shape. Exact accumulators keep the cost table's value. - saturation.rs: SaturationCurves loads out_grid_1e7_cost/ and out_1e9/ (1e9 wins) and applies the #156 rules: worse neighbour between checkpoints, worst bracketing grid point, curve metric must match, saturated panes for lossy merges (KLL, top-k). - MetricFacts.data_shape: fitted (zipf θ, K, tail index) per grouping. - An Accuracy oracle is threaded through eligibility, pruning, enumeration and minimize. - small_problem takes --saturation-dir. - Cost export sweeps grid configs: KLL k 200/800, CMS-heap cols 1024/4096. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cost-table sketch row and a saturation grid point measure the same thing, error at (sketch, config, data shape, N). They were keyed differently, so the optimizer could not tell that a row is one point on a curve. - aqpbm-core: MeasuredShape (Zipf θ and K, or Pareto a), the key both share, and MeasuredAt::data_shape(). - saturation.rs: grid points are keyed by MeasuredShape and keep seed_se. SaturationCurves::check_cost_table reads each sketch row's curve at measured_at. It reports a row as mismatched when the values disagree beyond 3 seed SEs + 5%, the config is not in the grid, or the table lacks the curve's metric. Rows with no point at their shape or N (KLL: Zipf ranks vs Pareto) are reported as unchecked. - small_problem refuses to plan on a mismatch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
be40f0d to
11e4e03
Compare
|
@milindsrivastava1997 I force-pushed this branch (with a lease on
Please pull with |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
||
| /// The oracle for [`crate::autosketch::plan`]: AutoSketch keeps one | ||
| /// unmerged sketch per query window. | ||
| pub fn autosketch_accuracy( |
There was a problem hiding this comment.
autosketch_accuracy has no caller. autosketch::plan itself has no non-test caller, and its tests still pass the table-based oracle, so the Q12 claim (AutoSketch-Adapted uses the curve lookup) isn't wired up or tested. Either hook it into the AutoSketch baseline and add a test, or drop it until it's needed.
| /// each of [`RUN_DIRS`] under `dir`. | ||
| pub fn load(dir: &Path) -> io::Result<Self> { | ||
| type PointKey = (String, String, String, String, String); | ||
| let key = |row: &CsvRow| -> PointKey { |
There was a problem hiding this comment.
load() keys rows by their raw param/cardinality strings, while scripts/study_saturation.py's point_key compares them numerically (pandas round-trips turn "1000" into "1000.0"). If the two CSVs, or the two runs, format a value differently, you get either curve row for a point not in saturation.csv, or duplicate points: bracketing_points then sees more matches than shape_params.len()*keys.len(), returns None, and silently makes the config ineligible. Parse these fields to numbers (or normalize them) before keying.
| facts: &WorkloadFacts, | ||
| ) -> Option<f64> { | ||
| let sketch = deployment.config.sketch.as_str(); | ||
| if sketch.starts_with("exact-") { |
There was a problem hiding this comment.
This detects exact accumulators by the "exact-" name prefix, but lib.rs already has a family registry (family_properties / the exact-* family list). Using the registry keeps "which families are exact" defined in one place.
| && (!properties.one_fixed_size_sketch_for_all_groups | ||
| || measured_at_group_count(&d.config, facts[&d.metric].cardinality[&d.grouping_labels])) | ||
| && r.accuracy_ok_for(&d.config, r.lookback_ms / d.window_ms) | ||
| && accuracy(r, d).is_some_and(|value| value.is_finite() && r.accuracy_ok(value)) |
There was a problem hiding this comment.
value.is_finite() && accuracy_ok(value) is also duplicated in autosketch.rs:153. Make it a single Raqe method (e.g. Raqe::meets_sla(Option<f64>)) so the MILP and the AutoSketch baseline can't drift apart on eligibility.
- FamilyProperties::exact marks the exact accumulators, so SaturationCurves::accuracy asks the registry instead of matching the "exact-" name prefix. - Raqe::meets_sla(Option<f64>) is the one accuracy-vs-SLA check, used by MILP eligibility and the AutoSketch search alike. Addresses review comments on #171. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since #171 every sketch read its plain curve at the lookback's item count, whatever the window, so a KLL or top-k answer merged from L/x windows got the unmerged sketch's accuracy. SaturationCurves now loads saturation_merge_curve.csv and reads it for those two families at m = L/x: the worse of the measured shard counts either side, the largest past it, and no accuracy without a merge curve. A later run's point keeps an earlier run's merge curves when it has none (out_1e9 measures none). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since #171 every sketch read its plain curve at the lookback's item count, whatever the window, so a KLL or top-k answer merged from L/x windows got the unmerged sketch's accuracy. SaturationCurves now loads saturation_merge_curve.csv and reads it for those two families at m = L/x: the worse of the measured shard counts either side, the largest past it, and no accuracy without a merge curve. A later run's point keeps an earlier run's merge curves when it has none (out_1e9 measures none). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…) (#179) * rqe-optimizer: merged KLL and top-k answers read the merge curves (#158) Since #171 every sketch read its plain curve at the lookback's item count, whatever the window, so a KLL or top-k answer merged from L/x windows got the unmerged sketch's accuracy. SaturationCurves now loads saturation_merge_curve.csv and reads it for those two families at m = L/x: the worse of the measured shard counts either side, the largest past it, and no accuracy without a merge curve. A later run's point keeps an earlier run's merge curves when it has none (out_1e9 measures none). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * rqe-optimizer: merge curves extrapolate only from a saturation they cover From review on #179: - Past a curve's last checkpoint, its plateau only if n_sat is at or before it: a merge curve stops at 1e7, while its point's n_sat may come from the 1e9 run. - A later run keeps an earlier run's merge curves at shard counts it didn't measure, moved rather than cloned. - load refuses a candidate KLL or top-k point with no merge curve, rather than leaving every merged deployment silently without accuracy. - shards must be a whole count >= 1; univmon-topk merges lossily too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * rqe-optimizer: no merged accuracy past the measured shard counts From the second review of #179: - Past the largest measured shard count, a merged KLL or top-k answer has no accuracy, rather than the largest count's: merge error grows with the count, and the study measures whatever counts a workload needs. - load refuses only a study with no merge curves at all (run without --merge-shards-list). A point without one, such as a 1e9-only point, just has no merged accuracy. - agrees_at takes the plateau under the same rule as curve_error_at (n_sat at or before the last checkpoint). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * rqe-optimizer: merged accuracy only where the merge curves measured it From the third review of #179: - The merge count is Deployment::query_instance_count, as in the cost model: no answer for a zero window or a lookback that isn't whole windows. - Past a merge curve's last N the merged answer is unknown. The plain curve's saturation says nothing about the merged sketch. A curve's last checkpoint itself is read as measured. - load refuses each lossy candidate sketch that has no merge curve at all, not only a study with none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Closes #156.
Sketch accuracy now comes from the saturation study's error-vs-N curves (#130, #140), read at the number of items a deployment's answer covers per group, at the workload's fitted data shape. Before, it came from the cost table's single measurement at N = 1e6. Exact accumulators keep the cost table's value.
Design decisions (please approve each)
This is a short version. The full questions, the options offered and the answers are in #156 under "Design decisions (Q&A)".
also require every pane to be saturatedamended: no pane check; like every sketch, they read the curve at the lookback's item count (after merging) (see the discussion below). Their merge penalty is rqe-optimizer: use merged accuracy curves for KLL and top-k #158.MetricFacts.data_shape(zipf skew, distinct keys, tail index), taken as the worst case over windows and groups. zipf skew describes whichever insertion mode the engine uses.error_metric(precision_at_k,mean_rank_err,relative_error; DDSketch moves tomean_relative_value_errorwith Report mean_relative_error for DDSketch (paper's relative-accuracy metric) #162/Report DDSketch relative value error #164). A mismatch means not eligible. Exact rows keep the cost table's 0.--saturation-dircontainingout_grid_1e7_cost/andout_1e9/(saturation.csvandsaturation_curve.csv), parsed in Rust. The 1e9 data wins.when merging, each pane must have each window's item count ≥ the saturation pointamended: read the curve at the lookback's item count whatever the window size, the same as every other sketch.SaturationCurves::autosketch_accuracy).Changes
rqe-optimizer/src/saturation.rs(new):DataShape, plusSaturationCurves::{load, accuracy, autosketch_accuracy}.rqe-optimizer/src/lib.rs:MetricFacts.data_shape;Accuracyoracle type andtable_accuracy;Raqe::accuracy_ok_for.candidates.rs,enumerate.rs,milp.rs: the oracle is passed throughis_eligible,eligible_deployments_for,prune_dominated_candidates,build_all_candidates,unservable,brute_force,for_each_mapping(_while)andminimize. Tests passtable_accuracy.examples/small_problem.rs: requires--saturation-dirand gives each grouping a data shape.scripts/export_rqe_optimizer_costs.sh: sweeps grid configs (Q4).aqpbm-core:MeasuredShape(Zipf skew and distinct keys, or Pareto tail index) andMeasuredAt::data_shape(). A cost-table row and a saturation grid point now share this key.SaturationCurves::check_cost_tablereads each sketch row's curve at itsmeasured_at. A row is mismatched if its value is off by more than 3 seed SEs + 5%, its config is off the grid, or it lacks the curve's metric. A row is unchecked if the study has no point at its shape or N (KLL: Zipf ranks vs. Pareto).small_problemrefuses to plan on a mismatch.docs/rqe_sketch_deployment_v1.md: documents the new eligibility rule.Not in this PR
check_cost_tableuses them as the cross-check.rqe-optimizer/data/autosketch-eval/README.md.Testing
After rebasing onto main (
table_accuracykeeps #154's merge-count bracketing for exact accumulators):cargo test -p rqe-optimizer: 58 passed.cargo clippy -p rqe-optimizer -p aqpbm-core --all-targets -D warnings: clean.cargo check --workspace --all-targets: clean.small_problem --cost-dir <2026-10-06 table> --saturation-dir <clnode109 curves>panics, as intended. Mismatched: KLL k=500 and CMS-heap cols=2048, which are off the grid. Unchecked: KLL, DD and HLL, because the study has no point at Zipf 1.1 / distinct keys 1e5. So the table still needs the re-export.Before the rebase:
cargo test -p rqe-optimizer: 46 passed, including 7 new tests insaturation.cargo clippy --all-targets -D warnings: clean.small_problemwith--saturation-dir .and the real cost tableout_10_6_26_1342:top_endpoints_1his unservable, because its top-k rows are cols=2048, which isn't in the grid.--milpserves all 8 RAQEs. After the Q2/Q11 amendment, KLL'slatency_p99_*RAQEs have 12–36 eligible deployments, up from 1.🤖 Generated with Claude Code