Commit a10b5c3
perf(plan): skip disabled windows in remove_intersecting_windows (3.1x faster planning) (#4505)
* perf(plan): skip disabled windows in remove_intersecting_windows
remove_intersecting_windows runs on every simulation - both Prediction.
run_prediction and run_prediction_kernel call it before simulating - so it sits
in front of the C++ kernel on the hot path. It scanned every charge window
against every export window, testing "is this charge window enabled" and "is
this export window enabled" inside the inner loop, so a plan carrying mostly
disabled windows still paid the full O(charge x export) scan to do nothing.
During optimisation that is the normal case, not an edge case. Instrumenting a
benchmark scenario: 266 charge windows per call of which 24.6 enabled, 48.8
export windows of which 16.0 enabled - 139 million pair-iterations scanned per
plan, of which 3.1% involved an enabled pair.
Enabled export windows are now collected once per call (returning immediately
when there are none, since nothing can clip), and a disabled charge window
short-circuits instead of scanning every export window to discover it cannot be
clipped. Both fast paths rebuild the window dicts exactly as the clipping path
does, so the returned windows carry the same keys and are equally freshly owned.
Profiled on the worst benchmark scenario, this function was 124.7s of a 152.9s
plan (81%). After: that scenario drops from 152.0s to 25.6s. Across the 20
scenario benchmark, mean optimise time falls from 13.674s to 4.359s (3.1x) with
plan metric and cost identical on all 20 - the clipping behaviour is unchanged,
only the work skipped.
Adds characterisation tests first: the fully-covered, disabled-charge,
disabled-export, clip-start, clip-end and split cases, plus a randomised
equivalence check comparing the implementation against a naive reference over
200 random window layouts. These pass before and after the change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(plan): single-pass clipping in remove_intersecting_windows, refresh random reference
Removes the "clip again" loop. It re-ran the whole clipping pass over every
charge window whenever a split left a tail long enough to keep, copying both
window lists each time. With export windows processed in start order the retry
cannot find anything: a head segment emitted by a split ends at the current
export window's start, and every later export window starts at or after that,
so nothing can reach back into it. Export windows are sorted here rather than
assumed sorted, so correctness does not depend on the caller.
This is not a speed-up - the benchmark is unchanged at 4.30s mean, so the retry
was rarely triggering. It is a simplification and a latent bug fix: on unsorted
input the old loop could emit a charge window overlapping an enabled export
window and then fail to revisit it, because the retry was only armed when the
remaining tail was at least 5 minutes long.
Verified by differential testing the new implementation against the original
from main over 300,000 random window layouts with sorted export windows (the
invariant callers provide): zero mismatches. Repeating with deliberately
unsorted export windows produces 495 disagreements in 200,000 layouts, and in
every one it is the old implementation that leaves a charge window overlapping
an enabled export.
The in-repo randomised equivalence test now generates sub-5-minute windows,
zero-length gaps and overlapping export windows, and runs 1000 layouts. Two
faults in its naive reference surfaced as a result and are fixed: an unclipped
window shorter than 5 minutes is kept rather than discarded, and windows that
merely touch at a boundary overlap arithmetically but clip nothing, so they
must not arm the minimum-length rule.
Also refreshes cases/random_results.json, which run_random compares against.
It was recorded on 2026-08-09 against the previous scenario set and was left
stale when the scenarios were regenerated in #4491, so run_random reported
large differences that were purely the scenario mismatch. Regenerated from the
current scenarios; the plans are identical with and without this change, so the
new reference is equally valid for main.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* [pre-commit.ci lite] apply automatic fixes
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>1 parent 7c2b765 commit a10b5c3
3 files changed
Lines changed: 506 additions & 241 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
| |||
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
62 | | - | |
63 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
64 | 108 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | 109 | | |
70 | | - | |
71 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
72 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
73 | 329 | | |
74 | 330 | | |
75 | 331 | | |
| |||
0 commit comments