Files
vac-optimizer/docs/benchmark/pr-278-immutable-date-counts.md

3.1 KiB
Raw Permalink Blame History

PR #278: reuse counts for immutable calendar dates

Measured on 2026-10-16 against c7e7abc, which already includes the direct date-key optimization.

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.

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.