nx_qplan_gate.nx source
↩ module page · 62 lines · 4095 B
1// nx_qplan_gate.nx -- proves the cost-based planner CHOOSES CORRECTLY, matching the reality the parexec
2// bench measured: small data -> sequential (fork not worth it); large bandwidth-bound scan -> sequential
3// (parallel loses, measured 0.66x); large compute-bound -> parallel (measured 3.10x). Also proves the
4// estimates are internally ordered and monotone. Known cost profiles, deterministic. D001 via nx_gate_verdict.
5import "nx_gate_verdict.nx"
6import "nx_qplan.nx"
7
8func qg_eq(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 }
9
10func main() -> i64 {
11 let ctr: *i64 = gv_ctr()
12 gv_head("nx_qplan_gate -- does the cost-based planner choose what the bench actually measured?" as *u8)
13
14 // ---- the three decisions the bench established -----------------------------------------------
15 // 1) tiny job (10k rows = 0.01 Mrows... use 1 Mrow with cw=0): bandwidth-bound + small -> SEQUENTIAL
16 gv_check("T1 1M-row pure SCAN -> SEQUENTIAL (fork cost + bus contention beat the saving)" as *u8, qg_eq(qp_choose(1, 0, 4), QP_SEQ), ctr)
17 // 2) large bandwidth-bound scan (40 Mrows, cw=0): parallel measured SLOWER -> SEQUENTIAL
18 gv_check("T2 40M-row pure SCAN -> SEQUENTIAL (matches the measured 0.66x -- parallel loses on bandwidth)" as *u8, qg_eq(qp_choose(40, 0, 4), QP_SEQ), ctr)
19 // 3) large compute-bound (40 Mrows, cw=32 like the hashsum): parallel measured 3.10x -> PARALLEL
20 gv_check("T3 40M-row COMPUTE-bound (cw=32) -> PARALLEL (matches the measured 3.10x)" as *u8, qg_eq(qp_choose(40, 32, 4), QP_PAR), ctr)
21
22 // ---- the cost estimates are sane and ordered ------------------------------------------------
23 // for a pure scan, parallel must be estimated MORE expensive than sequential (it is, by the model)
24 var t4: i64 = 0
25 if qp_cost_par(40, 0, 4) > qp_cost_seq(40, 0) { t4 = 1 }
26 gv_check("T4 pure-scan parallel estimate > sequential estimate (the model encodes the bus-contention penalty)" as *u8, t4, ctr)
27 // for heavy compute, parallel estimate must be LESS than sequential
28 var t5: i64 = 0
29 if qp_cost_par(40, 32, 4) < qp_cost_seq(40, 32) { t5 = 1 }
30 gv_check("T5 heavy-compute parallel estimate < sequential estimate" as *u8, t5, ctr)
31 // more cores -> lower parallel estimate for compute-bound (monotone in ncores)
32 var t6: i64 = 0
33 if qp_cost_par(40, 32, 8) < qp_cost_par(40, 32, 4) { t6 = 1 }
34 gv_check("T6 more cores lowers the compute-bound parallel estimate (scales with ncores)" as *u8, t6, ctr)
35
36 // ---- THE CROSSOVER is real: there is a compute-weight where the choice flips ------------------
37 // at cw=0 sequential; at cw=32 parallel; so some threshold in between flips it -> find it by scan
38 var flip: i64 = 0 - 1
39 var w: i64 = 0
40 while w <= 32 {
41 if flip < 0 { if qp_choose(40, w, 4) == QP_PAR { flip = w } }
42 w = w + 1
43 }
44 var t7: i64 = 0
45 if flip > 0 { if flip <= 32 { t7 = 1 } }
46 gv_check("T7 a real compute-weight CROSSOVER exists (below it sequential, at/above it parallel)" as *u8, t7, ctr)
47 // and below the crossover it is sequential, at it parallel -- the decision is a clean step, not noise
48 var t8: i64 = 1
49 if flip > 0 { if qp_choose(40, flip - 1, 4) != QP_SEQ { t8 = 0 } if qp_choose(40, flip, 4) != QP_PAR { t8 = 0 } } else { t8 = 0 }
50 gv_check("T8 the crossover is a clean step: cw=flip-1 sequential, cw=flip parallel" as *u8, t8, ctr)
51
52 // ---- the constants are DATA (conf-driven), not baked -----------------------------------------
53 // conf-driven: seed a sentinel default; if the conf is present the read must differ from the sentinel
54 var t9: i64 = 0
55 let probe: i64 = qp_conf("scan_us_per_mrow" as *u8, 0 - 999)
56 if probe != (0 - 999) { if probe > 0 { t9 = 1 } }
57 gv_check("T9 the scan-cost constant is READ from analyst_qplan.conf (not a code literal)" as *u8, t9, ctr)
58
59 let rc: i64 = gv_verdict("QPLAN-GATE" as *u8, ctr, "cost-based planner picks sequential vs parallel matching the measured bench, with a real crossover, from data-driven constants" as *u8)
60 sys_exit(rc)
61 return rc
62}