code wiki / _hdl_build / nx_burst_scheduler.nx
nx_burst_scheduler.nx source
↩ module page · 121 lines · 8427 B
1// nx_burst_scheduler.nx -- This module schedules task bursts to local, LAN, or cloud resources based on available budget and SLA requirements.
2import "nx_gate_gn.nx"
3import "nx_gate_base.nx"
4// nx_burst_scheduler.nx -- NAS-PRIMARY BURST-TO-POOL placement (operator: "run on the NAS and gen farm out to
5// this machine and other machines or cloud machines if it needs resources in excess of what the NAS can provide
6// to do the task in a reasonable time"). The MISSING policy that composes the existing pieces: per-node budget
7// (nx_resource_governor + nx_sysload), cross-host dispatch (nx_remote_worker over TCP), atomic work-claim
8// (nx_dispatch_lease). This decides PLACEMENT: do the work on the NAS if it can meet the reasonable-time SLA
9// alone; else burst the EXCESS to the pool -- this machine, then other machines, then CLOUD LAST (costliest) --
10// each node taking up to its governed budget; escalate if even the full pool can't meet the SLA.
11// T1 NAS-ALONE: a small task the NAS can finish in time -> stays local (no farm-out, no cloud cost).
12// T2 BURST TO THIS MACHINE: a task the NAS can't finish in time -> farms the excess to the workstation.
13// T3 BURST TO CLOUD: a task exceeding NAS + local machines -> reaches to cloud (only when needed).
14// T4 ESCALATE: a task exceeding the WHOLE pool within the SLA -> escalate (extend SLA or add resources).
15// T5 ORDER + BUDGET: cheapest/local first, cloud last; each node capped at its governed budget (no overwhelm).
16// license_tier: ORIGINAL
17import "nx_syscalls.nx"
18const TIER_MAGIC_50000: i64 = 50000
19
20// node tiers (cost/preference order: lower = preferred). cloud LAST (costliest).
21const TIER_NAS: i64 = 0
22const TIER_LOCAL: i64 = 1 // this machine / workstation
23const TIER_OTHER: i64 = 2 // other LAN machines
24const TIER_CLOUD: i64 = 3 // cloud (elastic but costliest -- only when needed)
25
26const PLAN_NAS_ALONE: i64 = 0
27const PLAN_BURSTED: i64 = 1
28const PLAN_ESCALATE: i64 = 2
29
30func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
31" as *u8); return ok }
32func tier_name(t: i64) -> *u8 { if t==TIER_NAS { return "NAS" as *u8 } if t==TIER_LOCAL { return "this-machine" as *u8 } if t==TIER_OTHER { return "other-LAN" as *u8 } return "CLOUD" as *u8 }
33
34// PLACE: greedily fill the needed throughput from the pool in TIER ORDER (nb/nt sorted ascending by tier).
35// needed_rate = ceil(task_cost / sla). alloc[i] = throughput taken from node i. returns PLAN_*.
36func plan_burst(task_cost: i64, sla: i64, nb: *i64, nt: *i64, nn: i64, alloc: *i64) -> i64 {
37 var needed: i64=(task_cost + sla - 1)/sla
38 var got: i64=0; var used: i64=0; var i: i64=0
39 while i<nn { alloc[i]=0; i=i+1 }
40 i=0
41 while i<nn {
42 if got<needed {
43 var take: i64=nb[i]
44 let still: i64=needed-got
45 if take>still { take=still }
46 if take>0 { alloc[i]=take; got=got+take; used=used+1 }
47 }
48 i=i+1
49 }
50 if got<needed { return PLAN_ESCALATE }
51 if used<=1 { return PLAN_NAS_ALONE }
52 return PLAN_BURSTED
53}
54// did the plan reach the cloud tier?
55func plan_uses_cloud(nt: *i64, alloc: *i64, nn: i64) -> i64 { var i: i64=0; while i<nn { if alloc[i]>0 { if nt[i]==TIER_CLOUD { return 1 } } i=i+1 } return 0 }
56
57func show_plan(label: *u8, verdict: i64, task: i64, sla: i64, nb: *i64, nt: *i64, nn: i64, alloc: *i64) -> i64 {
58 gw(" " as *u8); gw(label); gw(": task=" as *u8); gn(task); gw("u sla=" as *u8); gn(sla); gw("s need=" as *u8); gn((task+sla-1)/sla); gw("u/s -> " as *u8)
59 if verdict==PLAN_ESCALATE { gw("ESCALATE (pool can't meet SLA)\n" as *u8); return 0 }
60 if verdict==PLAN_NAS_ALONE { gw("NAS-ALONE" as *u8) } else { gw("BURST" as *u8) }
61 gw(" [" as *u8); var i: i64=0; var first: i64=1
62 while i<nn { if alloc[i]>0 { if first==0 { gw(" + " as *u8) } gw(tier_name(nt[i])); gw(":" as *u8); gn(alloc[i]); first=0 } i=i+1 }
63 gw("]\n" as *u8); return 0
64}
65
66func main() -> i64 {
67 gw("=== nx_burst_scheduler: NAS-primary, burst to this-machine/other/cloud by reasonable-time SLA (compose existing pieces) ===\n" as *u8)
68 var pass: i64=0; var total: i64=0
69
70 // the POOL (each budget = governed throughput units/sec from nx_resource_governor on that node; tiers ordered).
71 // NAS modest (sovereign server), this machine ~8 (the 16-core box, polite), other LAN ~8, cloud elastic-but-costly.
72 let nb: *i64=sys_mmap(64) as *i64; nb[0]=10; nb[1]=8; nb[2]=8; nb[3]=1000
73 let nt: *i64=sys_mmap(64) as *i64; nt[0]=TIER_NAS; nt[1]=TIER_LOCAL; nt[2]=TIER_OTHER; nt[3]=TIER_CLOUD
74 let NN: i64=4
75 let alloc: *i64=sys_mmap(64) as *i64
76
77 // T1: small task -> NAS alone (no farm-out, no cloud cost).
78 let v1: i64=plan_burst(20, 10, nb, nt, NN, alloc)
79 show_plan("T1 small " as *u8, v1, 20, 10, nb, nt, NN, alloc)
80 total=total+1; if v1==PLAN_NAS_ALONE { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
81 gw("T1 NAS-ALONE: a task the NAS finishes in time stays LOCAL (no farm-out)\n" as *u8)
82
83 // T2: task the NAS can't finish in time -> burst to this machine (NOT cloud yet).
84 let v2: i64=plan_burst(150, 10, nb, nt, NN, alloc)
85 show_plan("T2 medium" as *u8, v2, 150, 10, nb, nt, NN, alloc)
86 let cloud2: i64=plan_uses_cloud(nt, alloc, NN)
87 total=total+1; if v2==PLAN_BURSTED { if cloud2==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
88 gw("T2 BURST TO THIS MACHINE: NAS over-subscribed -> farm excess to the workstation (cloud untouched)\n" as *u8)
89
90 // T3: task exceeding NAS + local machines -> reach cloud (only when needed).
91 let v3: i64=plan_burst(300, 10, nb, nt, NN, alloc)
92 show_plan("T3 large " as *u8, v3, 300, 10, nb, nt, NN, alloc)
93 let cloud3: i64=plan_uses_cloud(nt, alloc, NN)
94 total=total+1; if v3==PLAN_BURSTED { if cloud3==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
95 gw("T3 BURST TO CLOUD: exceeds NAS+LAN -> reach cloud (last resort, only when needed for the SLA)\n" as *u8)
96
97 // T4: task exceeding the WHOLE pool within SLA -> escalate.
98 let v4: i64=plan_burst(TIER_MAGIC_50000, 10, nb, nt, NN, alloc)
99 show_plan("T4 huge " as *u8, v4, TIER_MAGIC_50000, 10, nb, nt, NN, alloc)
100 total=total+1; if v4==PLAN_ESCALATE { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
101 gw("T4 ESCALATE: even the full pool can't meet the SLA -> escalate (extend the deadline or add resources) -- no silent miss\n" as *u8)
102
103 // T5: ORDER (cheapest/local first, cloud last) + per-node budget respected.
104 let v5: i64=plan_burst(150, 10, nb, nt, NN, alloc) // re-plan the medium task
105 var order_ok: i64=1
106 if alloc[0]!=10 { order_ok=0 } // NAS filled first to its budget (10)
107 if alloc[1]<=0 { order_ok=0 } // then this machine
108 if alloc[3]!=0 { order_ok=0 } // cloud NOT used (not needed)
109 var budget_ok: i64=1; var i: i64=0
110 while i<NN { if alloc[i]>nb[i] { budget_ok=0 } i=i+1 } // never exceed a node's governed budget
111 total=total+1; if order_ok==1 { if budget_ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
112 gw("T5 ORDER+BUDGET: filled NAS(" as *u8); gn(alloc[0]); gw(")->this-machine(" as *u8); gn(alloc[1]); gw("), cloud untouched(" as *u8); gn(alloc[3]); gw("), no node over its governed budget\n" as *u8)
113
114 gw("\n CORRECTED TOPOLOGY WIRED: the NAS is PRIMARY; work stays local when it fits the reasonable-time SLA; only the EXCESS\n" as *u8)
115 gw(" farms out -- this machine, then other LAN machines, then CLOUD LAST -- each capped at its governed budget (nx_resource_\n" as *u8)
116 gw(" governor), dispatched over nx_remote_worker, claimed via nx_dispatch_lease. Cloud is the costliest last resort, never\n" as *u8)
117 gw(" the default. Escalates rather than silently missing the SLA. = NAS-primary burst-to-pool, composing existing pieces.\n" as *u8)
118 gw("BURST-SCHEDULER verdict=" as *u8)
119 if pass==total { gw("GREEN passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw(" -- NAS-primary burst-to-pool placement (local-first, cloud-last, SLA-driven, budget-capped)\n" as *u8); sys_exit(0); return 0 }
120 gw("RED passes=" as *u8); gn(pass); gw("/" as *u8); gn(total); gw("\n" as *u8); sys_exit(1); return 1
121}