@@ -6,7 +6,7 @@ use rqe_optimizer::candidates::build_all_candidates;
66use rqe_optimizer:: enumerate:: unservable;
77use rqe_optimizer:: milp:: { minimize, MilpSolution , Objective } ;
88use rqe_optimizer:: {
9- validate_facts , AccuracyDirection , AtomicCostEntry , Capability , LabelSet , Raqe , WorkloadFacts ,
9+ table_accuracy , validate_facts , AtomicCostEntry , Capability , LabelSet , Raqe , WorkloadFacts ,
1010} ;
1111use thiserror:: Error ;
1212
@@ -15,11 +15,6 @@ use crate::config::input::ControllerConfig;
1515use super :: pipeline:: { extract_hinted_items, OptimizerPipelineError } ;
1616use super :: solution:: OptimizerItem ;
1717
18- /// `query_accuracy` keys in sketch-bench's cost export. Each is the worst case
19- /// its comparator reports.
20- const RELATIVE_ERROR : & str = "relative_error" ;
21- const MAX_RANK_ERROR : & str = "max_rank_err" ;
22- const PRECISION_AT_K : & str = "precision_at_k" ;
2318/// Slack on accuracy tolerances so `1 - sla` rounding (`1 - 0.9 =
2419/// 0.0999...98`) doesn't reject a row measured exactly at the boundary.
2520const SLA_EPSILON : f64 = 1e-9 ;
@@ -55,8 +50,13 @@ pub fn solve_milp(
5550 objective : Objective ,
5651 allow_undeployable_families : bool ,
5752) -> Result < MilpSolution , MilpError > {
58- let deployments =
59- build_all_candidates ( & workload. raqes , costs, facts, allow_undeployable_families) ;
53+ let deployments = build_all_candidates (
54+ & workload. raqes ,
55+ costs,
56+ facts,
57+ allow_undeployable_families,
58+ & table_accuracy,
59+ ) ;
6060 tracing:: debug!(
6161 candidates = deployments. len( ) ,
6262 cost_rows = costs. len( ) ,
@@ -71,12 +71,18 @@ pub fn solve_milp(
7171 . filter ( |& ( i, _) | i == 0 || workload. raqe_items [ i] != workload. raqe_items [ i - 1 ] )
7272 . map ( |( _, raqe) | raqe. clone ( ) )
7373 . collect ( ) ;
74- let missing = unservable ( & one_per_item, & deployments, facts) ;
74+ let missing = unservable ( & one_per_item, & deployments, facts, & table_accuracy ) ;
7575 if !missing. is_empty ( ) {
7676 return Err ( MilpError :: Unservable ( missing) ) ;
7777 }
78- let solution = minimize ( & workload. raqes , & deployments, facts, objective)
79- . map_err ( |e| MilpError :: Solver ( e. to_string ( ) ) ) ?;
78+ let solution = minimize (
79+ & workload. raqes ,
80+ & deployments,
81+ facts,
82+ objective,
83+ & table_accuracy,
84+ )
85+ . map_err ( |e| MilpError :: Solver ( e. to_string ( ) ) ) ?;
8086 tracing:: debug!(
8187 objective = objective. value( & solution. plan_cost) ,
8288 cpu_secs_per_sec = solution. plan_cost. cpu_secs_per_sec( ) ,
@@ -129,9 +135,7 @@ pub fn build_milp_workload(
129135 grouping_labels = ?raqe. grouping_labels,
130136 lookback_ms = raqe. lookback_ms,
131137 interval_ms = raqe. interval_ms,
132- accuracy_metric = %raqe. accuracy_metric,
133138 accuracy_sla = raqe. accuracy_sla,
134- accuracy_direction = ?raqe. accuracy_direction,
135139 latency_sla_ms = ?raqe. latency_sla_ms,
136140 "milp inputs: item -> raqe"
137141 ) ;
@@ -182,8 +186,7 @@ fn item_to_raqe(item: &OptimizerItem) -> Result<Raqe, MilpError> {
182186 accuracy_sla : item. accuracy_sla ,
183187 } ) ;
184188 }
185- let ( accuracy_metric, accuracy_sla, accuracy_direction) =
186- accuracy_target ( capability, item. accuracy_sla ) ;
189+ let accuracy_sla = accuracy_target ( capability, item. accuracy_sla ) ;
187190
188191 // TopK keeps one heap per `topk by` bucket; its `grouping_labels` is the
189192 // output label set (every label), which would cost one heap per series.
@@ -204,9 +207,7 @@ fn item_to_raqe(item: &OptimizerItem) -> Result<Raqe, MilpError> {
204207 metric : req. metric . clone ( ) ,
205208 spatial_filter : req. spatial_filter_normalized . clone ( ) ,
206209 grouping_labels,
207- accuracy_metric : accuracy_metric. to_string ( ) ,
208210 accuracy_sla,
209- accuracy_direction,
210211 latency_sla_ms : item. latency_sla_ms ,
211212 } )
212213}
@@ -232,24 +233,17 @@ fn capability(statistic: Statistic, topk_count_events: Option<bool>) -> Option<C
232233
233234/// `accuracy_sla` is required accuracy: error metrics must stay within
234235/// `1 - accuracy_sla`, and top-k precision must reach `accuracy_sla`.
235- fn accuracy_target (
236- capability : Capability ,
237- accuracy_sla : f64 ,
238- ) -> ( & ' static str , f64 , AccuracyDirection ) {
236+ fn accuracy_target ( capability : Capability , accuracy_sla : f64 ) -> f64 {
239237 let max_error = 1.0 - accuracy_sla + SLA_EPSILON ;
240238 match capability {
241239 Capability :: Sum
242240 | Capability :: Count
243241 | Capability :: Min
244242 | Capability :: Max
245243 | Capability :: RateOrIncrease
246- | Capability :: Cardinality => ( RELATIVE_ERROR , max_error, AccuracyDirection :: LowerIsBetter ) ,
247- Capability :: Quantile => ( MAX_RANK_ERROR , max_error, AccuracyDirection :: LowerIsBetter ) ,
248- Capability :: TopKByValue | Capability :: TopKByCount => (
249- PRECISION_AT_K ,
250- accuracy_sla - SLA_EPSILON ,
251- AccuracyDirection :: HigherIsBetter ,
252- ) ,
244+ | Capability :: Cardinality
245+ | Capability :: Quantile => max_error,
246+ Capability :: TopKByValue | Capability :: TopKByCount => accuracy_sla - SLA_EPSILON ,
253247 }
254248}
255249
@@ -265,6 +259,7 @@ pub(super) mod tests {
265259 const FACTS : & str = r#"
266260metrics:
267261 - metric: http_requests_total
262+ value_range: [1.0, 1000.0]
268263 groups:
269264 - labels: [instance, job]
270265 cardinality: 100
@@ -316,11 +311,11 @@ metrics:
316311
317312 pub ( crate ) fn costs ( ) -> Vec < AtomicCostEntry > {
318313 vec ! [
319- cost( "exact-sum" , & [ ( RELATIVE_ERROR , 0.0 ) ] ) ,
320- cost( "kll-percall" , & [ ( MAX_RANK_ERROR , 0.005 ) ] ) ,
314+ cost( "exact-sum" , & [ ( "relative_error" , 0.0 ) ] ) ,
315+ cost( "kll-percall" , & [ ( "mean_rank_err" , 0.005 ) ] ) ,
321316 cost(
322317 "cms-heap-topk-fastpath-vector2d" ,
323- & [ ( PRECISION_AT_K , 0.995 ) ] ,
318+ & [ ( "precision_at_k" , 0.995 ) ] ,
324319 ) ,
325320 ]
326321 }
@@ -341,11 +336,13 @@ metrics:
341336 "quantile_over_time(0.99, http_requests_total[5m])" ,
342337 0.9 ,
343338 ) ) ;
344- assert ! ( w. raqes[ 0 ] . accuracy_ok( 0.1 ) ) ;
345- assert ! ( !w. raqes[ 0 ] . accuracy_ok( 0.1001 ) ) ;
339+ assert ! ( w. raqes[ 0 ] . meets_sla( "kll-percall" , Some ( 0.1 ) ) ) ;
340+ assert ! ( w. raqes[ 0 ] . meets_sla( "dd" , Some ( 0.1 ) ) ) ;
341+ assert ! ( !w. raqes[ 0 ] . meets_sla( "kll-percall" , Some ( 0.1001 ) ) ) ;
342+ assert ! ( !w. raqes[ 0 ] . meets_sla( "dd" , Some ( 0.1001 ) ) ) ;
346343 let w = workload ( & group ( "topk(5, http_requests_total)" , 0.9 ) ) ;
347- assert ! ( w. raqes[ 0 ] . accuracy_ok ( 0.9 ) ) ;
348- assert ! ( !w. raqes[ 0 ] . accuracy_ok ( 0.8999 ) ) ;
344+ assert ! ( w. raqes[ 0 ] . meets_sla ( "cms-heap-topk-fastpath-vector2d" , Some ( 0.9 ) ) ) ;
345+ assert ! ( !w. raqes[ 0 ] . meets_sla ( "cms-heap-topk-fastpath-vector2d" , Some ( 0.8999 ) ) ) ;
349346 }
350347
351348 #[ test]
@@ -374,8 +371,6 @@ metrics:
374371 let r = & w. raqes [ 0 ] ;
375372 assert_eq ! ( r. capability, Capability :: Sum ) ;
376373 assert_eq ! ( r. grouping_labels, labels( & [ "job" ] ) ) ;
377- assert_eq ! ( r. accuracy_metric, RELATIVE_ERROR ) ;
378- assert_eq ! ( r. accuracy_direction, AccuracyDirection :: LowerIsBetter ) ;
379374 assert ! ( ( r. accuracy_sla - 0.01 ) . abs( ) < 1e-6 ) ;
380375 assert_eq ! ( r. interval_ms, 60_000 ) ;
381376 assert_eq ! ( r. latency_sla_ms, None ) ;
@@ -410,14 +405,14 @@ metrics:
410405 }
411406
412407 #[ test]
413- fn quantile_uses_max_rank_error ( ) {
408+ fn quantile_uses_the_error_ceiling ( ) {
414409 let w = workload ( & group (
415410 "quantile_over_time(0.99, http_requests_total[5m])" ,
416411 0.99 ,
417412 ) ) ;
418413 let r = & w. raqes [ 0 ] ;
419414 assert_eq ! ( r. capability, Capability :: Quantile ) ;
420- assert_eq ! ( r . accuracy_metric , MAX_RANK_ERROR ) ;
415+ assert ! ( ( r . accuracy_sla - 0.01 ) . abs ( ) < 1e-6 ) ;
421416 assert_eq ! ( r. lookback_ms, 300_000 ) ;
422417 }
423418
@@ -426,8 +421,6 @@ metrics:
426421 let w = workload ( & group ( "topk by (job) (5, http_requests_total)" , 0.9 ) ) ;
427422 let r = & w. raqes [ 0 ] ;
428423 assert_eq ! ( r. capability, Capability :: TopKByValue ) ;
429- assert_eq ! ( r. accuracy_metric, PRECISION_AT_K ) ;
430- assert_eq ! ( r. accuracy_direction, AccuracyDirection :: HigherIsBetter ) ;
431424 assert ! ( ( r. accuracy_sla - 0.9 ) . abs( ) < 1e-6 ) ;
432425 // Not the all-labels output set, which would cost one heap per series.
433426 assert_eq ! ( r. grouping_labels, labels( & [ "job" ] ) ) ;
0 commit comments