Score fallback and report reuse (2026-10-11)¶
Report now reuses its raw leaderboard and corrected winners for dashboard
summaries under mcs and legacy. The 12-file mcs benchmark has 24 → 12 full
load calls, equivalent tables/charts, and 28.1% lower median report runtime.
seq_mcs retains independent dashboard collection after report persists all
wealth updates, so earlier files see the final store. Decoder settings remain
parallel="none", low_memory=True.
Implemented in: serve/score_scan.py, dashboard/score_summary.py,
dashboard/context.py, dashboard/writer.py, cli.py, reports/eprocess.py
Source and reproduction¶
The baseline is 4019cc661653af8955d265fc29ecd53f0f805736. The measured source is
saved as a source patch against that
revision. Applying it to the baseline was verified to reconstruct the measured
source exactly. Source hashes cover filenames and bytes under src, excluding
Python caches and Finder metadata.
POLARS_MAX_THREADS=2 OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1 \
uv run --locked python scripts/benchmark_score_readers.py \
--baseline 4019cc6 --runs 3 --evaluations 12 --cases 4000 \
--output docs/research/score-readers-2026-10-11.jsonl
Every sample runs in a fresh process against immutable source and score fixtures.
Dataset, artifacts, history, and report outputs use isolated temporary paths.
Input/source hashes are checked after measurement. Dataset/config/code identities
are fixed, and recorder/dashboard clocks remain fixed to 2026-10-10 UTC, matching
the previous experiment. No tests or other benchmark
workloads run concurrently. PYTHONHASHSEED=0; the four thread settings above are
applied to every worker.
The baseline uses the bounded policy; the updated source is measured under all
three existing policies: bounded (parallel="none", low_memory=True), auto low
memory (parallel="auto", low_memory=True), and auto (parallel="auto",
low_memory=False). Peak RSS is total process resource.ru_maxrss, including
imports and decoding. Wall time covers the entry point and comparison payload
extraction.
The renamed metric full_load_calls counts load_scores invocations. It
excludes projected Parquet scans and batches used by selection. A selection count
of zero still involves reading metadata and selected score rows. Historical
samples, including their full_decodes field, remain unchanged.
Fixtures and equivalence¶
Fixtures and their hashes match the previous experiment. Both selection archives have 12 files, four methods, one hourly slice, and an 8,196-byte repeated feature JSON value. Many evaluations has 192,000 rows, selecting the newest 16,000; mostly incompatible has 176,320 rows, selecting 320 from the only compatible evaluation. Their compressed sizes are 639,492 and 595,454 bytes respectively.
Standalone dashboard and report share a 384,000-row, 644,196-byte archive:
12 files, four methods, two hourly slices (temp_c and pop), and three quantile
levels (0.1, 0.5, 0.9). Temperature challenger errors alternate around reference
error to keep sequential wealth finite; PoP predictions are 0.5 with alternating
binary truths. This retains the existing fixture that avoids an unrelated
baseline math.exp(log_e) overflow.
All 48 samples agree on their comparison payload within each workload across sources, policies, and repetitions. Full report comparisons include every leaderboard Markdown table and dashboard chart. Table rows are sorted for comparison because tied aggregate errors have undefined display order; headers and values remain included. Raw rendered hashes are saved separately.
The benchmark uses mcs. Deterministic regressions separately verify equivalent
reused and independently collected summaries under both mcs and legacy,
including pooled daily gates, synthetic scores, and empty archives. They assert
one full load per file, release before the next decode, and rendering after
source files disappear. seq_mcs retains two loads per file; a two-file regression
confirms that its dashboard reflects later persisted wealth, preserves store
cursors, and leaves settled report tables and ledgers unchanged on further runs.
Complete fitting and real deployment archives are outside these measurements.
Measurements¶
Python 3.13.14, Polars 1.42.1, macOS-27.0.1-arm64-arm-64bit-Mach-O.
Baseline source SHA-256: 12adf9728c3a0a2a1fa129ac7ccc469defba2b37c2f36bed42d0c73174fbaf9b.
Updated source SHA-256: 80d5ef6a67e040a61909d3adc358bd7270baaf1e0c3b584ab02686f4077aca3b.
Runner SHA-256: 4d2a5b0cd89b47ac186dd1652691964cc213304185689f098c90243147f10861.
Combined fixture SHA-256: 484976b1b3420b3241e43065d60cafb0dc55c5da176db8e8c05d7c88aa8e24aa.
Ranges are minimum–maximum across three fresh processes. MiB is \(2^{20}\) bytes.
| Workload | Source / policy | Median RSS (MiB) | RSS range | Median time (s) | Time range | Full load calls |
|---|---|---|---|---|---|---|
| many evaluations | Baseline / bounded | 260.80 | 260.69–260.83 | 0.1989 | 0.1987–0.2167 | 0 |
| many evaluations | Updated / bounded | 261.56 | 260.78–262.72 | 0.2018 | 0.1988–0.2057 | 0 |
| many evaluations | Updated / auto low memory | 260.33 | 258.88–260.67 | 0.1982 | 0.1982–0.2050 | 0 |
| many evaluations | Updated / auto | 260.11 | 259.22–261.03 | 0.2013 | 0.1986–0.2055 | 0 |
| mostly incompatible | Baseline / bounded | 151.45 | 151.23–151.67 | 0.0316 | 0.0313–0.0343 | 0 |
| mostly incompatible | Updated / bounded | 151.34 | 151.16–151.70 | 0.0316 | 0.0314–0.0319 | 0 |
| mostly incompatible | Updated / auto low memory | 151.59 | 151.36–153.17 | 0.0320 | 0.0316–0.0328 | 0 |
| mostly incompatible | Updated / auto | 151.16 | 151.14–151.41 | 0.0313 | 0.0312–0.0360 | 0 |
| dashboard | Baseline / bounded | 293.92 | 293.52–295.23 | 3.8834 | 3.8663–4.0352 | 12 |
| dashboard | Updated / bounded | 291.14 | 290.64–293.09 | 3.8880 | 3.8773–3.9890 | 12 |
| dashboard | Updated / auto low memory | 294.16 | 293.20–296.34 | 4.0042 | 3.8718–4.0835 | 12 |
| dashboard | Updated / auto | 293.94 | 292.19–294.55 | 3.8818 | 3.8602–4.0339 | 12 |
| report | Baseline / bounded | 305.72 | 304.64–307.30 | 6.7075 | 6.7002–6.7184 | 24 |
| report | Updated / bounded | 304.77 | 302.92–305.95 | 4.8193 | 4.8137–4.9282 | 12 |
| report | Updated / auto low memory | 304.77 | 304.48–305.45 | 4.8205 | 4.8100–4.9434 | 12 |
| report | Updated / auto | 304.41 | 302.27–305.89 | 4.9734 | 4.7732–6.0642 | 12 |
The bounded report's runtime ranges do not overlap, and its median improves by 28.1%. Report RSS ranges overlap, so this does not establish a general memory improvement. Standalone dashboard still loads each file once and has nearly the same median runtime. Selection runtime ranges overlap, with small RSS variation. Neither automatic policy establishes the required clear runtime improvement across workloads; bounded decoding remains in place.
Raw JSONL samples and aggregated JSON contain exact source, runner, fixture, thread, payload, and load-count evidence. The previous dated artifacts remain historical; their different baseline makes absolute timings unsuitable for measuring this change. Three samples describe the observed spread.
Correctness, validation, and rollout¶
Score selection now invalidates every affected evaluation across all slices and reconsiders the newest remaining complete evaluation within the same catalog. That finite loop continues only while the invalid set grows. Unknown catalog failures or no-progress materialization failures consume at most three fresh catalog attempts, then fail closed. Three materialization-time prunes can therefore fall back to an older complete evaluation without exhausting that outer retry budget. See model selection.
PIT and reliability failures are isolated independently from core scoring and from each other. Valid leaderboards, winners, and other diagnostics survive; failed diagnostics use local amber warnings without making live scores unusable. For example, ragged quantile grids can fail PIT while valid CRPS/coverage and PoP reliability remain visible. See dashboard diagnostics.
The full suite passes 1,400 tests, with 13 skips and 91.78% coverage.
All CONTRIBUTING.md gates pass: lockfile/host checks, Ruff, both type checkers,
Semgrep tests/scans, dependency hygiene, packaging (10/10), complexity (maximum
27 against ceiling 27), and strict documentation build. Regressions include
fallback progress/exhaustion, whole-evaluation exclusion, independent diagnostic
failures, report reuse, final sequential wealth, and cached policy-neutral store
loading.
Deploying the changed source rotates the code fingerprint. Before rollout,
refresh compatible evidence with backtest --source live and report; existing
forecast artifacts retain their last-good behavior during that transition.
Deployment installation and live evidence refresh are outside this implementation.