vyre_driver/
persistent_kernel_policy.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct PersistentKernelInputs {
23 pub batch_size: u32,
25 pub per_launch_overhead_ns: u64,
29 pub per_item_kernel_ns: u64,
32 pub persistent_setup_overhead_ns: u64,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum PersistentKernelDecision {
41 StandardLaunches,
46 PersistentKernel {
49 savings_ns: u128,
53 },
54}
55
56#[must_use]
65pub fn decide_persistent_kernel(inputs: PersistentKernelInputs) -> PersistentKernelDecision {
66 if inputs.batch_size <= 1 {
67 return PersistentKernelDecision::StandardLaunches;
68 }
69 if inputs.per_launch_overhead_ns == 0 {
72 return PersistentKernelDecision::StandardLaunches;
73 }
74 let standard_overhead =
75 u128::from(inputs.batch_size) * u128::from(inputs.per_launch_overhead_ns);
76 let persistent_setup_overhead_ns = u128::from(inputs.persistent_setup_overhead_ns);
77 if standard_overhead <= persistent_setup_overhead_ns {
78 return PersistentKernelDecision::StandardLaunches;
79 }
80 let savings_ns = standard_overhead - persistent_setup_overhead_ns;
81 PersistentKernelDecision::PersistentKernel { savings_ns }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 fn inp(batch: u32, launch_ovh: u64, item_ns: u64, setup: u64) -> PersistentKernelInputs {
89 PersistentKernelInputs {
90 batch_size: batch,
91 per_launch_overhead_ns: launch_ovh,
92 per_item_kernel_ns: item_ns,
93 persistent_setup_overhead_ns: setup,
94 }
95 }
96
97 #[test]
98 fn single_launch_is_always_standard() {
99 let dec = decide_persistent_kernel(inp(1, 5_000, 1_000, 1_000));
102 assert_eq!(dec, PersistentKernelDecision::StandardLaunches);
103 }
104
105 #[test]
106 fn zero_batch_is_standard() {
107 let dec = decide_persistent_kernel(inp(0, 5_000, 1_000, 50_000));
108 assert_eq!(dec, PersistentKernelDecision::StandardLaunches);
109 }
110
111 #[test]
112 fn small_batch_below_amortisation_threshold_is_standard() {
113 let dec = decide_persistent_kernel(inp(5, 5_000, 1_000, 50_000));
116 assert_eq!(dec, PersistentKernelDecision::StandardLaunches);
117 }
118
119 #[test]
120 fn batch_at_amortisation_threshold_is_standard() {
121 let dec = decide_persistent_kernel(inp(10, 5_000, 1_000, 50_000));
124 assert_eq!(dec, PersistentKernelDecision::StandardLaunches);
125 }
126
127 #[test]
128 fn large_batch_above_threshold_picks_persistent() {
129 let dec = decide_persistent_kernel(inp(100, 5_000, 1_000, 50_000));
132 assert_eq!(
133 dec,
134 PersistentKernelDecision::PersistentKernel {
135 savings_ns: 450_000
136 }
137 );
138 }
139
140 #[test]
141 fn portable_typical_overheads_pick_persistent_at_modest_batch() {
142 let dec = decide_persistent_kernel(inp(10, 25_000, 5_000, 200_000));
145 assert_eq!(
146 dec,
147 PersistentKernelDecision::PersistentKernel { savings_ns: 50_000 }
148 );
149 }
150
151 #[test]
152 fn zero_per_launch_overhead_returns_standard() {
153 let dec = decide_persistent_kernel(inp(1000, 0, 100, 50_000));
156 assert_eq!(dec, PersistentKernelDecision::StandardLaunches);
157 }
158
159 #[test]
160 fn savings_is_strictly_positive_for_persistent_verdict() {
161 let dec = decide_persistent_kernel(inp(1000, 5_000, 1_000, 50_000));
162 match dec {
163 PersistentKernelDecision::PersistentKernel { savings_ns } => {
164 assert!(savings_ns > 0);
165 }
166 other => panic!("expected PersistentKernel; got {:?}", other),
167 }
168 }
169
170 #[test]
171 fn item_duration_does_not_affect_decision() {
172 let small_kernel = decide_persistent_kernel(inp(100, 5_000, 100, 50_000));
176 let large_kernel = decide_persistent_kernel(inp(100, 5_000, 1_000_000, 50_000));
177 assert_eq!(small_kernel, large_kernel);
178 }
179
180 #[test]
181 fn widened_arithmetic_preserves_extreme_savings() {
182 let dec = decide_persistent_kernel(inp(u32::MAX, u64::MAX / 2, 1, 50_000));
185 match dec {
186 PersistentKernelDecision::PersistentKernel { savings_ns } => {
187 assert_eq!(
188 savings_ns,
189 u128::from(u32::MAX) * u128::from(u64::MAX / 2) - 50_000
190 );
191 }
192 other => panic!("expected PersistentKernel; got {:?}", other),
193 }
194 }
195
196 #[test]
197 fn persistent_policy_source_uses_exact_widened_arithmetic() {
198 let source = include_str!("persistent_kernel_policy.rs");
199
200 assert!(
201 !source.contains(concat!("saturating", "_mul"))
202 && !source.contains(concat!("saturating", "_sub")),
203 "Fix: persistent-kernel policy must use exact widened arithmetic, not saturating launch-cost math."
204 );
205 assert!(
206 source.contains("u128::from(inputs.batch_size)")
207 && source.contains("u128::from(inputs.per_launch_overhead_ns)")
208 && source.contains("standard_overhead - persistent_setup_overhead_ns"),
209 "Fix: persistent-kernel savings must stay widened through the verdict."
210 );
211 }
212}