Cut per-patch overhead in apply/iapply#55
Merged
Merged
Conversation
Micro pass over the patch interpreter (Track E): - Dispatch on the parent's exact class first (dict/list fast paths) and only fall back to hasattr duck typing for container look-alikes such as observ proxies, instead of paying up to three hasattr calls on every patch - Skip the defensive deepcopy for immutable scalar patch values (deepcopy returns the same object for those anyway); non-scalar values are still copied on write, so patches and patched objects never share mutable state - Skip the int() conversion for keys that are already ints (native pointers), keeping the try/except only for parsed string tokens - Bind deepcopy and the scalar-type set to locals outside the loop Adds two op-heavy apply benchmarks (400 dict ops; 100 replaces three levels deep) since the existing one was dominated by the deep copy of the base object. Interleaved benchmark medians vs master (2 runs each, including the base-object copy that apply() always pays): apply_dict_many_ops 652.9us -> 577.9us (-11.9%) apply_list_1000_elements 254.4us -> 227.5us (-10.3%) apply_nested_paths 289.8us -> 262.4us (-9.4%) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Mu9vEBwU4fQLi8ZgkgdS2
Korijn
force-pushed
the
claude/apply-micro
branch
from
July 11, 2026 10:37
e671f80 to
b1a135b
Compare
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Track E, PR 12 — the apply/iapply micro pass.
What
dict/listfast paths), falling back tohasattrduck typing only for container look-alikes such as observ proxies — instead of paying up to threehasattrcalls on every patch. Duck-typed parents take exactly the same branches as before.deepcopyfor immutable scalar patch values (deepcopyreturns the same object for those anyway — semantically identical). Non-scalar values are still copied on write, so the "patches never share mutable state with your objects" guarantee is unchanged, and the docs statement stays true as written.int()conversion for keys that are already ints (native pointers); thetry/except ValueErrorremains for parsed string tokens.deepcopyand the scalar-type set to locals outside the loop.Benchmarks
The apply group had one benchmark, dominated by the base-object deep copy, so this PR adds two op-heavy cases (400 mixed dict ops; 100 replaces addressed three levels deep). Interleaved medians vs master, 2 runs each (all numbers still include the base-object copy
apply()always pays, so the op-loop itself improved by more):405 tests pass at 100% coverage (property round-trips and the RFC 6902 corpus both exercise this interpreter heavily); ruff and ty clean. Independent of the other Track E PRs — merges in any order.
🤖 Generated with Claude Code
https://claude.ai/code/session_016Mu9vEBwU4fQLi8ZgkgdS2
Generated by Claude Code