Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agents/DEVELOPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Cheat sheet of what's been considered. Issue numbers are the entry points — fe

- **Cache thread-safety / concurrency** (umbrella #444). Enabling refactor #569 is **fully landed** (PRs #601, #604, #622): `BaseCache(OperationContext)` and `Cache(PerKeyLockMixin, BaseCache)` — lock mixins now attach at the cache layer too. Storage layer was already thread-safe (per-key locks; #213, #449 closed). Cache-level races whose **fixes landed**: #217 (back-fill via PR #629, issue closed), #452 (transfer contains→save TOCTOU via PR #630, issue closed), #485 (in-flight dedup window via PR #627, issue closed). #451 (redigest atomicity) — PR #631 shipped the cross-key lock but the **issue is still open** pending follow-up review; cite the PR, not "#451 closed". Still open: `gc` #450, `expand` lock scope #453. (Wrapper check→execute→save #448 closed not-planned.) `BackgroundSaveMixin` (#447) is the planned vehicle for moving disk I/O off the hot path while `save()` keeps returning a key synchronously.

- **Performance hot-spots** (#625, #440). One open digest hot-spot: `_digest_bytes` returns hex-encoded bytes that double parent SHA256 input at every nesting level — fix needs a `hash_version` bump + `Cache.redigest` migration. BLAKE3 tree-hashing was the structural alternative; the hash-function recon issue (#614, **closed 2026-06-02**) concluded with **blake2b(digest_size=32)** as the cheaper migration (stdlib, ~35-40% faster on tree workloads, 64-char hex preserved so `DIGEST_LENGTH` / SQL schema / `D()` pass-through all stay put). #615 is the open Option-A switchover; semver-breaking (invalidates persistent keys; users run `redigest()` once on upgrade). `Perf audit:` issues are refreshed periodically — check the latest one (currently #625, refreshed 2026-08-20) for current numbers; previous audits #527 (2026-05-28), and the older ones it supersedes, are closed. The 2026-06-11/18/25 runs all pin PR #622's cache-layer `PerKeyLockMixin` double-lock penalty (×1.54–2.0 on memory-backend miss/save across all data_heavy workloads — hit/contains unchanged); the storage-layer side of the same double-lock motivated the `init=False, hash=False` storage-dict option in #634's review, which the `__init_subclass__` guard in PR #683 sidestepped without addressing the perf side, so the double-lock cost is still open. The 2026-06-18 run's ×13 H5+Sql data_heavy miss spike did **not** recur on 2026-06-25 (7.8 ms vs 8.3 ms) — confirmed I/O jitter, not a code regression — but `BagOfHoldingH5File` still pays a structural ×5 over `PickleFile` on save (full HDF5 file open/close per `put`/`get`); fix candidates are h5py SWMR / pooled file handles in `bagofholding_file.py`. Hot-spot #2 from earlier audits (per-element `sha256()` allocation in recursive iterables/dicts) was retracted on review — the per-element context is load-bearing for the Merkle-tree property and has no cheap fix. SQL evict hot-spot from the 2026-05-21 audit was resolved by PR #535 (bulk DELETE in place of ORM materialisation), and the earlier BagOfHolding double-open by PR #616.
- **Performance hot-spots** (#625, #440). One open digest hot-spot: `_digest_bytes` returns hex-encoded bytes that double parent SHA256 input at every nesting level — fix needs a `hash_version` bump + `Cache.redigest` migration. BLAKE3 tree-hashing was the structural alternative; the hash-function recon issue (#614, **closed 2026-06-02**) concluded with **blake2b(digest_size=32)** as the cheaper migration (stdlib, ~35-40% faster on tree workloads, 64-char hex preserved so `DIGEST_LENGTH` / SQL schema / `D()` pass-through all stay put). #615 is the open Option-A switchover; semver-breaking (invalidates persistent keys; users run `redigest()` once on upgrade). `Perf audit:` issues are refreshed periodically — check the latest one (currently #625, refreshed 2026-08-27: no new source-caused regressions; every flagged row is the chronic `BagOfHoldingH5File` per-op open cost or measurement noise) for current numbers; previous audits #527 (2026-05-28), and the older ones it supersedes, are closed. The 2026-06-11/18/25 runs all pin PR #622's cache-layer `PerKeyLockMixin` double-lock penalty (×1.54–2.0 on memory-backend miss/save across all data_heavy workloads — hit/contains unchanged); the storage-layer side of the same double-lock motivated the `init=False, hash=False` storage-dict option in #634's review, which the `__init_subclass__` guard in PR #683 sidestepped without addressing the perf side, so the double-lock cost is still open. The 2026-06-18 run's ×13 H5+Sql data_heavy miss spike did **not** recur on 2026-06-25 (7.8 ms vs 8.3 ms) — confirmed I/O jitter, not a code regression — but `BagOfHoldingH5File` still pays a structural ×5 over `PickleFile` on save (full HDF5 file open/close per `put`/`get`); fix candidates are h5py SWMR / pooled file handles in `bagofholding_file.py`. Hot-spot #2 from earlier audits (per-element `sha256()` allocation in recursive iterables/dicts) was retracted on review — the per-element context is load-bearing for the Merkle-tree property and has no cheap fix. SQL evict hot-spot from the 2026-05-21 audit was resolved by PR #535 (bulk DELETE in place of ORM materialisation), and the earlier BagOfHolding double-open by PR #616. Still open on the SQL side: `Sql` commits (and fsyncs) once per key on `save`/`evict` — `_configure_sqlite_pragmas` sets `journal_mode=WAL` but no `synchronous` pragma, so every `commit()` still fsyncs; the audits' cheap fix (`PRAGMA synchronous=NORMAL`, safe under WAL), flagged in every run since 2026-05-07, is untouched.

Two long-open perf PRs, unmerged — check before duplicating. **Draft PR #786** (opened 2026-07-23) already implements the pooled-file-handle candidate above: a process-wide cache of read-only `h5py.File` handles (`_BagHandleCache` — bounded MRU of 32, `(inode, mtime_ns, size)` stat-signature invalidation, `locking=False`, writers close the cached handle under a per-bag lock) takes multi-bag `contains` from 240 µs back to ~29 µs (the pre-#746 per-key baseline); `evict` is deliberately untouched (structurally must pay filelock + HDF5 write open). Cold `list()` over many bags is the remaining cost — the PR body enumerates the options (per-bag key-list cache, persistent index) without committing to one.

Expand Down
Loading