@@ -80,6 +80,8 @@ asap-planner-rs/src/optimizer/
8080├── candidate_gen.rs enumerate candidate configs per AQE [Phase 2b, done]
8181├── cost_model.rs ingest/query cost formulas [Phase 2c, done]
8282├── greedy.rs per-AQE greedy assignment [Phase 2e, done]
83+ ├── atomic_costs.rs (sketch_type, params) → AtomicCosts, from
84+ │ sketch-bench's exported table [Phase 2f, done, #549]
8385│
8486│ ── TO BE ADDED ──
8587├── feasibility.rs Feasible(a,g) predicate — only meaningful once configs
@@ -222,6 +224,33 @@ placeholder value applied uniformly to every candidate — see open TODO below.
222224a real `aggregation_id `, emits one `QueryConfig ` per original query string , with
223225`num_aggregates_to_retain ` from `retention_count_for_assignment ()`.
224226
227+ #### 2f — `atomic_costs . rs` (done , issue #549 , carved out of #524 )
228+
229+ `greedy . rs` no longer applies one global `AtomicCosts ` to every candidate . Per candidate :
230+
231+ ```rust
232+ pub fn resolve_atomic_costs (table : & AtomicCostTable , agg_type : AggregationType ,
233+ params : & HashMap <String , Value >) -> Option <AtomicCosts >
234+ ```
235+
236+ - `CountMinSketch ` / `HLL ` / `DatasketchesKLL `: translated to sketch - bench 's `(algorithm , params )`
237+ key (`sketch_bench_key ()` — field names are duplicated from `candidate_gen . rs`'s `param_grid ()`,
238+ not derived from it , so a rename on either side without the other panics loudly instead of
239+ silently mismatching ) and looked up by exact key in the table . No match for that exact param
240+ point → `None `, candidate dropped .
241+ - Every other `AggregationType ` (trivial accumulators like `Sum `/ `MinMax `, and sketches
242+ sketch - bench doesn 't wrap yet like `CountMinSketchWithHeap `/ `HydraKLL `) → `Some (AtomicCosts :: default ())`,
243+ the pre - #549 flat stub , with a `tracing :: warn! `. * * This means costs for those families are still
244+ param - invariant ** (e . g. `CountMinSketchWithHeap ` currently costs identically regardless of
245+ `depth `/ `width `/ `heapsize ` — see #524 for the analytic memory bound that 's supposed to replace
246+ the stub for it ).
247+ - No `subtract_cpu_secs ` in the table (asap_sketchlib has no `subtract ` yet — asap_sketchlib #69 ) —
248+ always comes from the stub constant regardless of family .
249+
250+ `AtomicCostEntry `/ `AtomicCostTable ` are a deliberate duplicate of sketch - bench 's
251+ `aqpbm_core :: atomic_costs ` types (same reasoning as the field - name duplication above : sketch - bench 's
252+ schema is still actively churning , so no shared crate dependency yet — see PR #547 's discussion ).
253+
225254---
226255
227256### 🔲 Phase 3 — Full MIP with Cross - AQE Sharing
@@ -236,11 +265,18 @@ Add `run_mip_pipeline()` to `pipeline.rs`.
236265Relax `labels_compatible ()` in `asap_types :: capability_matching ` at line 86 (TODO comment already there ).
237266Allow a config with labels ⊇ query labels to serve that AQE . This is what enables cross - AQE sharing .
238267
239- #### 3c — sketch - bench cardinality sweep
268+ #### 3c — real ` AtomicCosts ` from sketch - bench
240269
241- - Add cardinality to sweep grids in `sketch - bench `
242- - Add `CountMinSketchWithHeap ` wrapper in `sketch - cli / src / wrappers / `
243- - Plug real `AtomicCosts ` values into cost model
270+ - ✅ Plug real `AtomicCosts ` values into cost model — done for CMS / HLL / KLL , see 2f above and
271+ " Running with real sketch-bench costs" below .
272+ - ❌ Add `CountMinSketchWithHeap ` wrapper in sketch - bench , so it stops always costing at the flat
273+ stub . Its memory is meant to be an analytic bound (`heap_size · avg_key_size `), not a
274+ sketch - bench lookup at all , per #524 — that formula still needs implementing in
275+ `atomic_costs . rs`/ `cost_model . rs`.
276+ - ~~Add cardinality to sweep grids in `sketch - bench `~~ — decided unnecessary : CPU / mem costs for
277+ CMS / HLL / KLL are functions of structural params (depth ×width , lg_k , K ), not cardinality : only
278+ `CountMinSketchWithHeap ` is cardinality - dependent , and that 's the analytic - bound case above , not
279+ a sketch - bench sweep axis .
244280
245281#### 3d — Accuracy constraint
246282
@@ -265,14 +301,45 @@ standalone `asap-optimizer-cli` binary (`asap-planner-rs/src/bin/optimizer_cli.r
265301```
266302cargo run - p asap_planner -- bin asap - optimizer - cli -- \
267303 -- input_config <path / to / workload . yaml> \
268- -- prometheus_scrape_interval 60 \
269- [-- rho 1.0 ]
304+ -- data - ingestion - interval - ms 60000 \
305+ [-- rho 1.0 ] \
306+ [-- atomic - costs <path / to / atomic_costs . json>]
270307```
271308
272309Takes the same `ControllerConfig ` YAML format as `asap - planner -- input_config `
273310(with a `metrics : ` hints block for label schema — no live Prometheus needed ).
274311Prints deployed streaming configs and query configs to stdout . `-- rho ` is the
275- placeholder arrival rate (see TODOs below — not real yet ).
312+ placeholder arrival rate (see TODOs below — not real yet ). `-- atomic - costs ` is
313+ optional ; omit it and every candidate costs at the flat stub , same as before #549 .
314+
315+ ### Running with real sketch - bench costs
316+
317+ * * 1 . Generate the table , in the `sketch - bench ` repo : **
318+
319+ ```
320+ ./scripts/export_atomic_costs.sh
321+ # → out/atomic_costs.json — one row per (sketch, params) point in ASAPQuery's grid,
322+ # built by looping candidate_gen.rs's CMS_DEPTHS×CMS_WIDTHS/HLL_PRECISIONS/KLL_KS
323+ # through ` approxbench sketchbench --flat ` and reducing with ` approxbench atomic-costs ` .
324+ ```
325+
326+ **2. Feed it to ASAPQuery**, either binary:
327+
328+ ```
329+ # See what each candidate would cost, before selection:
330+ cargo run -p asap_planner --bin candidate-gen-dump -- \
331+ --input_config workload.yaml --data-ingestion-interval-ms 60000 \
332+ --atomic-costs path/to/atomic_costs.json
333+
334+ # Run the actual optimizer:
335+ cargo run -p asap_planner --bin asap-optimizer-cli -- \
336+ --input_config workload.yaml --data-ingestion-interval-ms 60000 \
337+ --atomic-costs path/to/atomic_costs.json
338+ ```
339+
340+ `candidate-gen-dump`'s output labels each params row `[real]` (resolved from the table) or
341+ `[stub]` (fell through to `AtomicCosts::default()` — either an unbenchmarked family, or a
342+ benchmarked family's param point missing from the table).
276343
277344Wire-in decision (deferred): once Phase 3 (MIP + feasibility + label superset
278345matching) lands, swap `Controller::generate()` to call `run_mip_pipeline()`
0 commit comments