Skip to content

Cut per-call overhead in the produce proxy traps#57

Merged
berendkleinhaneveld merged 1 commit into
masterfrom
claude/produce-micro
Jul 13, 2026
Merged

Cut per-call overhead in the produce proxy traps#57
berendkleinhaneveld merged 1 commit into
masterfrom
claude/produce-micro

Conversation

@Korijn

@Korijn Korijn commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Track E, PR 13 — the trap-level micro pass, the analog of observ #192/#193.

What

  • Scalar fast path in _wrap: scalar reads skip the child-proxy cache lookup and the hasattr chain entirely (scalars never have a cached child proxy — cache entries only exist for container values). Inlined additionally in DictProxy/ListProxy __getitem__ for the hottest read shape.
  • DictProxy.__setitem__ resolves the old value with one sentinel data.get() instead of a containment check plus a read. On plain dicts that's a wash, but when the draft wraps an observ reactive proxy (in_place=True), each of those was a trapped operation with dep tracking — two trapped calls become one.
  • values()/items() iterate _data.items() once instead of re-reading every key, with the scalar check inlined; ListProxy.__iter__/__reversed__ get the same treatment plus bound locals.
  • ListProxy.append and the slice read path bind hot attributes to locals and drop intermediate temporaries.

Two small tests are added for the new early-return paths (scalar list reads by index, tuple values through _wrap), keeping coverage at 100%. Behavior is unchanged; 408 tests pass, ruff and ty clean.

Benchmarks

Interleaved medians vs the memoization branch (#54), 2 runs each:

benchmark before after change
produce_in_place_vs_copy_dict (writes through an observ reactive draft) 192.3µs 156.6µs −18.6%
produce_list_many_appends[copy/in_place] −1.8% / −2.0%
everything else within noise (±1.5%)

An honest note on magnitude: the write-heavy plain-dict workloads were already lean (the sentinel-get trades two dict lookups for one method call, which is a wash on plain dicts), so the wins concentrate where the pass targets — read paths and proxy-backed drafts.

🤖 Generated with Claude Code

https://claude.ai/code/session_016Mu9vEBwU4fQLi8ZgkgdS2

@Korijn
Korijn force-pushed the claude/produce-hotpath branch 2 times, most recently from 1d172c7 to 044f769 Compare July 11, 2026 10:46
@Korijn
Korijn force-pushed the claude/produce-micro branch from f859b50 to 8a21b2d Compare July 11, 2026 10:46
@Korijn

Korijn commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

@berendkleinhaneveld I'll let you review & approve this one

@Korijn
Korijn force-pushed the claude/produce-hotpath branch from 044f769 to f5e4fe8 Compare July 11, 2026 10:54
@Korijn
Korijn force-pushed the claude/produce-micro branch from 8a21b2d to 96e5166 Compare July 11, 2026 10:55
@Korijn
Korijn changed the base branch from claude/produce-hotpath to master July 11, 2026 10:56
@Korijn
Korijn force-pushed the claude/produce-micro branch from 5197c6c to eec5507 Compare July 11, 2026 11:00
Trap-level micro pass (Track E), on top of the location memoization:

- Scalar fast path in _wrap: scalar reads skip the cache lookup and
  the hasattr chain entirely (scalars never have a cached child proxy:
  cache entries only exist for container values), inlined additionally
  in DictProxy/ListProxy __getitem__ for the hottest read shape
- DictProxy.__setitem__ resolves the old value with one sentinel
  data.get() instead of a containment check plus a read - two trapped
  operations become one when the draft wraps an observ proxy
- values()/items() iterate _data.items() once instead of re-reading
  every key, with the scalar check inlined; ListProxy __iter__ and
  __reversed__ get the same treatment plus bound locals
- ListProxy.append and the slice read path bind hot attributes to
  locals and drop intermediate temporaries

Two small tests added for the new early-return paths (scalar list
reads by index, tuple values through _wrap), keeping coverage at 100%.

Interleaved benchmark medians vs the memoization branch (2 runs each):

  produce_in_place_vs_copy_dict (writes through an
    observ reactive draft)                 192.3us -> 156.6us (-18.6%)
  produce_list_many_appends               -1.8% / -2.0%
  everything else                         within noise (+/-1.5%)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Mu9vEBwU4fQLi8ZgkgdS2
@Korijn
Korijn force-pushed the claude/produce-micro branch from 7f4e219 to cea03cc Compare July 13, 2026 07:13
@berendkleinhaneveld
berendkleinhaneveld merged commit 193b6fb into master Jul 13, 2026
11 checks passed
@berendkleinhaneveld
berendkleinhaneveld deleted the claude/produce-micro branch July 13, 2026 07:17
@Korijn Korijn mentioned this pull request Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants