Skip to content

typing/perf 5: Rc refine cache + schema-level junction cache (−30–47% across the board) - #84

Open
Felipe705x wants to merge 1 commit into
tc-perf/04-path-summaryfrom
tc-perf/05-rc-caches
Open

typing/perf 5: Rc refine cache + schema-level junction cache (−30–47% across the board)#84
Felipe705x wants to merge 1 commit into
tc-perf/04-path-summaryfrom
tc-perf/05-rc-caches

Conversation

@Felipe705x

Copy link
Copy Markdown
Collaborator

Stacked on #83. First autonomous-session milestone.

Cache hits stop paying clone costs:

  • refine memo stores Rc<VariableType> → hit = refcount bump (was: deep clone of the refined union per hit; subq_exists alone did 43 of those per check).
  • New Schema::junction_nodes memo: PathSummary's junction refinement is cached cross-hop and cross-query. New kill switch GQLITE_DISABLE_TC_JUNCTION_CACHE; the differential suite now pins the full 2×2 switch matrix.
  • Rejected during review-by-proptest: meet(a,a)=a fast paths — idempotence is pinned only up to mutual subtyping, so short-circuiting risks structural/warning drift.

Idle-machine medians (LDBC SF0.1 schema), vs #83:

case #83 this PR
chain_1 14.9 µs 8.8 µs
chain_16 234 µs 141 µs
chain_dir_16 280 µs 147 µs
union_8 146 µs 94 µs
subq_exists 61 µs 41.5 µs
multi_optional 108 µs 77 µs
anon_16 (cliff guard) 24.1 ms 12.7 ms

Every case now beats every previous state in the series (vs session baseline: chain_16 −69%, subq −40%). check/parse ratio on typical shapes: 4–12×.

🤖 Generated with Claude Code

Two cache upgrades that eliminate the remaining clone traffic on hits:

- `refine_rc`: the refine memo now stores `Rc<VariableType>`; a hit is a
  refcount bump instead of a deep clone of the refined descriptor tree.
  The env operators (which store `Rc` bindings anyway) and the pattern
  refinement sites consume the Rc directly; `refine()` stays as the
  by-value API for reference models. `refine_to_nodes` borrow-walks the
  shared tree and clones only matching Node leaves.
- `Schema::junction_nodes`: PathSummary's junction refinement
  (refine_to_nodes(meet(last, first)) flattened to descriptors) is now
  memoized on the Schema — cross-hop AND cross-query (a chain reuses one
  junction at every position). Nested map so lookups clone no keys; kill
  switch GQLITE_DISABLE_TC_JUNCTION_CACHE; differential test extended to
  the 2×2 switch matrix.

Considered and REJECTED: meet(a,a)=a fast paths — lattice_proptest pins
meet idempotence only up to mutual subtyping (explicitly not canonical
equality), so short-circuiting could change result structure and
warning text.

Idle-machine numbers vs the PathSummary state (previous best), all
prior states beaten on every case:
- chain_1     14.9 → 8.8 us (−41%)   chain_16   234 → 141 us (−40%)
- chain_dir_16 280 → 147 us (−47%)   anydir_8   130 → 94 us (−28%)
- union_8     146 → 94 us (−36%)     subq_exists 61 → 41.5 us (−32%)
- multi_optional 108 → 77 us (−29%)  repeat_1_3  15.5 → 10 us (−35%)
- anon_16 cliff guard 24.1 → 12.7 ms
- check/parse ratios: typical shapes now 4–12× (from 10–30×)

vs the original session baseline: chain_1 −55%, chain_16 −69%,
subq_exists −40%.

Full sweep 80 targets green; hom proptest and 2×2 cache differential
green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant