fix(benchmarks): don't measure hit-phase timing against evicted keys - #804
fix(benchmarks): don't measure hit-phase timing against evicted keys#804pmrv wants to merge 2 commits into
Conversation
SizeLimitedCache evicts uniformly at random (SizeLimitedMixin._pick_eviction_target), so populating a cache smaller than `iterations` with unique keys doesn't guarantee any particular subset survives. benchmark_integration's "contains hit" and "hit" phases blindly reused the full original arg list, silently re-measuring misses (and re-inserts) for keys evicted during the miss phase. Restrict both phases to args confirmed resident via `func.contains()` right after the miss phase, and report the actual sample size used. Refs #150. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mzs4Bw7dsBUC4bXhhjWmoQ
|
Claude finished @pmrv's task in 3m 47s —— View job Done — replaced the
|
The SizeLimitedCache(max=10) config could never measure hits: the cache instance is shared by all three benchmark functions, so it accumulates 3 * 20 == 60 call records while keeping only 10. Since SizeLimitedMixin._pick_eviction_target evicts uniformly at random, the "contains hit" and "hit" phases re-measured misses (recompute + re-save) for the ~50 evicted keys. Size the config above the workload instead of filtering the hit phases: max_size=100 already exceeds the 60 keys inserted, so nothing is evicted and every hit-phase call is a real hit. The deliberately-undersized variant is dropped (it would otherwise duplicate the max=100 config once enlarged), and the benchmark loop is back to its original form. Co-authored-by: Marvin Poul <2719909+pmrv@users.noreply.github.com>
…theme (#889) Scheduled AGENTS.md audit, 2026-08-23. No code has landed on `main` since the 2026-08-21 audit (63a0584), and the issue/PR state recorded in `agents/DEVELOPING.md` is still current: in-flight PRs #873–#878, #881, #887, and #797 all remain open; no new issues since #883–#886. Spot-checks of the Quick Reference and Architecture claims against `src/` all pass (public `__all__`, `_lazy_default`/`_sticky_set`/`_hard_set`, `PreparedCall`/two-phase save, `register_storage`, `_CACHE_TEMPLATES`, `Runtime.cputime`/`systime`, module line counts quoted in #789/#832). `AGENTS.md` and `agents/USAGE.md` need no changes. One gap found: the performance theme names "pooled file handles in `bagofholding_file.py`" as a fix candidate without noting that draft PR #786 (open since 2026-07-23) already implements it, and PR #804 (open since 2026-07-31) — the benchmark-harness fix that removes the always-evicting `SizeLimitedCache(max_size=10)` config — was recorded nowhere. Both are now listed under the perf theme as check-before-duplicating entries, added as separate paragraphs to keep future edits conflict-free. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01H9uSJpX8SLJrtYbc2ZaSv5 --- _Generated by [Claude Code](https://claude.ai/code/session_01H9uSJpX8SLJrtYbc2ZaSv5)_ Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com>
…qlFile fsync cheap fix (#898) Weekly AGENTS.md/DEVELOPING.md audit. Only one change since the 2026-08-27 pass (#897): issue #625's perf audit was refreshed the same morning. - Update the perf-audit pointer in `agents/DEVELOPING.md` from "refreshed 2026-08-20" to 2026-08-27 and record the run's verdict (no new source-caused regressions; flagged rows are the chronic `BagOfHoldingH5File` per-op open cost or noise). - Record the still-open SQL-side hot spot the refreshed audit re-flags: `Sql` fsyncs once per key on `save`/`evict` because `_configure_sqlite_pragmas` (`src/fleche/storage/sql.py:190-227`) sets `journal_mode=WAL` but no `synchronous` pragma; the cheap fix (`PRAGMA synchronous=NORMAL`) has been flagged in every audit since 2026-05-07. Verified against the source — the function sets only `foreign_keys` and `journal_mode`. Everything else checked and current: no merges to `main` since #897; open PRs (#873, #874, #887, #892, #894, #896, #797, #786, #804) and issues (#893, #895, #625) are all already recorded. `eisenforschung/landau` was audited in the same pass and needs no update (nothing landed since its 2026-08-25 pass; in-flight PRs #391/#394/#395/#414/#422 unchanged; spot-checked claims hold). --- _Generated by [Claude Code](https://claude.ai/code/session_012SCLy9y7aUR7F44Q7UviGo)_ Co-authored-by: Claude <noreply@anthropic.com>
…racker items (#904) Scheduled AGENTS.md audit. Changes since the 2026-08-27 pass: - Release-state claims updated: PR #793 (two-phase save) and PR #843 (lock-free pickle-family backends) shipped in 0.22.0 on 2026-08-28 (release PR #837); the three "unreleased as of 2026-08-27" qualifiers are gone. Noted that `fix(query)` #894 is an ancestor of the 0.22.0 tag (verified via `git tag --contains c82c691`) even though the generated changelog entry omits it. - PR #894 (`latest()`/`oldest()` raise `ValueError` when no matching call carries `Runtime` metadata, `IndexError` on empty), PR #892 (gc mid-sweep guards + 441-case digest product collapse, suite 1738 → 1299), and docs-audit PRs #873/#874 moved from the in-flight section to decisions landed; the in-flight section is now a one-liner pointing at the five PRs still open (#887, #804, #797, #786, #523), each covered under its theme. - New tracker items recorded: the 2026-08-28 refactor cohort #899–#902, bug #903 (`put()` `filelock.Timeout` fatality on ≤0.21.2, dedup-concentrated lock contention; resolved for pickle-family by 0.22.0's atomic rename, bagofholding multi-bag still exposed per #893), and the #895 resolution (documented limitation per the 2026-08-28 maintainer comment). #900 cross-referenced at the `pypi-publish.yml` line in the workflows list. - The #893 bullet's `lock_timeout` mitigation sentence rephrased to the current state: the `FutureWarning` drop covers only pickle-family configs, a bagofholding `values.lock_timeout` still works on 0.22.0 (checked against `config.py:466`). - USAGE.md: query section states the `latest()`/`oldest()` `ValueError`/`IndexError` contract (verified against `query.py:149-188`). landau's AGENTS.md was audited in the same pass and left unchanged — no code or tracker movement since its 2026-08-24 update (only docs commits on main; issues #423–#425 and PRs #422/#414/#395/#394/#391 unchanged). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_014myhh6xKWC2VhQeB92mGSn --- _Generated by [Claude Code](https://claude.ai/code/session_014myhh6xKWC2VhQeB92mGSn)_ Co-authored-by: Claude <noreply@anthropic.com>
Summary
SizeLimitedMixin._pick_eviction_targetevicts uniformly at random, andmax_sizecaps call records for the whole cache instance —main()'sSizeLimitedCacheconfigs are shared across all three benchmarked functions (lightweight/compute_heavy/data_heavy), so a config accumulates3 * iterations = 60call records over its lifetime. The oldSizeLimitedCache(Memory,max=10)config therefore held only 10 of those 60 keys at any time, and the "contains hit"/"hit" phases blindly reused all 20 args per function assuming they were still resident — most of those calls were silently re-measuring misses (recompute + re-save), corrupting the reported hit-phase timing.Per @pmrv's review feedback, fixed by removing the undersized config rather than adding residency-tracking logic: dropped
SizeLimitedCache(Memory,max=10)and kept onlySizeLimitedCache(Memory,max=100), whose capacity (100) exceeds the 60 records this config ever accumulates, so no eviction occurs and every "hit"-phase call is a genuine hit. The measurement loop itself is unchanged — the whole diff is in the config list.Any
max_sizelarge enough to stop evicting (≥ 60) would make a second entry a duplicate of the existingmax=100config, so a differently-sized "with evictions" variant wasn't reintroduced.Test plan
python benchmarks/benchmark_integration.pyruns end-to-end, valid JSON, 72 results (was 84 with the extra config)SizeLimitedCachehit-phase results now reportiterations: 20(genuine hits) for all three functionsruff check/ruff format --checkpass on the changed file🤖 Generated with Claude Code
https://claude.ai/code/session_01Mzs4Bw7dsBUC4bXhhjWmoQ