perf(planning): reuse immutable non-working date counts
This commit is contained in:
1 parent
c7e7abcd24
commit
433a8b0ade
3 files changed
+95
-3
No files matched your search
@@ -0,0 +1,61 @@
|
||||
# PR #278: reuse counts for immutable calendar dates
|
||||
|
||||
Measured on 2026-10-16 against `c7e7abc`, which already includes the
|
||||
[direct date-key optimization](pr-278-date-keys.md).
|
||||
|
||||
A loaded-year CPU profile attributed 4.06 of 69.37 seconds to repeatedly counting
|
||||
distinct non-working dates for time-off-period objectives. The existing calendar
|
||||
cache already shares frozen date arrays between candidate plans, but each score
|
||||
rebuilt a `Set` to count the same dates again.
|
||||
|
||||
The objective evaluator now keeps those counts in a `WeakMap` keyed by the frozen
|
||||
array. Mutable arrays are recounted on every evaluation. The weak keys allow
|
||||
unused arrays to be collected, and configuration validation and duplicate-date
|
||||
handling remain intact. This change touches only that scoring operation.
|
||||
|
||||
## Before and after
|
||||
|
||||
Both protocol runs used Node 24.18.0, Bun 1.3.14 and Vitest 5.0.3 on the same local
|
||||
machine. The baseline is the completed run recorded for `c7e7abc`; its saved core
|
||||
bundle is byte-for-byte identical to a fresh bundle of that commit. No other
|
||||
test, build or profiling workload ran alongside either protocol measurement.
|
||||
|
||||
```sh
|
||||
NODE_OPTIONS=--max-old-space-size=2048 timeout 300s bunx vitest run src/app/benchmark/leave-planner-benchmark.spec.ts --maxWorkers=1
|
||||
```
|
||||
|
||||
All seven warm-ups, fourteen measured calculations, the typed-obligation precheck,
|
||||
fixtures, assertions and resource limits remain unchanged.
|
||||
|
||||
| Measurement | Before | After |
|
||||
| ---------------------------------------------- | --------: | --------: |
|
||||
| Entire command, external wall time | 268.573 s | 256.034 s |
|
||||
| Benchmark test | 263.265 s | 250.652 s |
|
||||
| Loaded year, mean of two measured calculations | 67.747 s | 64.360 s |
|
||||
| Headroom before timeout | 31.427 s | 43.966 s |
|
||||
|
||||
The full command was 4.7% faster in this pair. Both runs completed successfully,
|
||||
and every repeated scenario remained deterministic. Live CI performance still
|
||||
needs confirmation.
|
||||
|
||||
An isolated check using the loaded-year plan's frozen date arrays took
|
||||
551–554 ms before and 46–57 ms after for 100,000 scoring calls, following 5,000
|
||||
warm-ups per run in before/after/after/before order. That result isolates the repeated
|
||||
counting cost; the protocol above measures its effect on complete calculations.
|
||||
|
||||
## Correctness checks
|
||||
|
||||
Complete outcomes, stable explanations and final-state snapshots match `c7e7abc`
|
||||
for all seven scenarios. These separate comparisons ran alongside functional
|
||||
checks; their diagnostic timings are not used in the protocol comparison.
|
||||
|
||||
The functional coverage suite passes all 638 tests across 33 files. Three new
|
||||
regression cases cover duplicate dates and changes to mutable arrays alongside
|
||||
frozen arrays for sum, count and maximum scores. Application and spec type checks,
|
||||
lint, formatting and `git diff --check` also pass.
|
||||
|
||||
No browser timing run or live CI rerun was performed for this change.
|
||||
|
||||
Diagnostic sources, profiles, bundles and full logs are retained in
|
||||
`/tmp/vac-opt278-step2`. The original core diagnostic runner is documented in
|
||||
[issue-78.md](issue-78.md#reproduction).
|
||||
Reference in new issue
Block a user