Skip to content

typing/perf 8: interned type ids + meet/join memos (subq/optional −32%) - #87

Open
Felipe705x wants to merge 1 commit into
tc-perf/07-env-costsfrom
tc-perf/08-meet-memo
Open

typing/perf 8: interned type ids + meet/join memos (subq/optional −32%)#87
Felipe705x wants to merge 1 commit into
tc-perf/07-env-costsfrom
tc-perf/08-meet-memo

Conversation

@Felipe705x

Copy link
Copy Markdown
Collaborator

Stacked on #86.

The counters showed subquery/OPTIONAL shapes spending their time in genuine VariableType::meet/join walks (22–44 per check) over rich refined types. This PR memoizes refine(meet(a,b)) and the env-join arms by interned type id: bindings carry a lazily-computed u32 (a Cell cache, invisible to the API), the Schema interns each distinct type once, and repeat lattice work becomes an integer-pair lookup — cross-query, like every cache in this stack. Kill switch GQLITE_DISABLE_TC_MEET_CACHE; differential matrix extended.

vs #86: subq_exists 22.9 → 15.6 µs, multi_optional 43.6 → 29.0 µs, union_8 50 → 34 µs.

Cumulative vs the pre-series baseline: chain_16 10.5×, subqueries 4.4×, unions 5.3×, the pathological unlabeled ×16 case ~5500× (23.3 s → 4.2 ms). Trivial queries now check at or below parse cost (0.69–0.95×); typical shapes sit at 2.3–6.4× parse.

🤖 Generated with Claude Code

The remaining subquery/OPTIONAL cost was genuine lattice work: 22–44
VariableType::meet/join walks over rich refined types per check. Those
walks are now memoized by interned type id:

- Schema gains a VariableType interner (canonical Rc per distinct
  value — first Rc seen wins, which keeps downstream Rc::ptr_eq fast
  paths hitting) plus two memos: meet_refine_cache for the env-meet
  step refine(meet(a,b)) — including the collapse-error outcome, whose
  message regenerates identically from the operand types — and
  join_cache for the env-join arms (order-sensitive key, matching
  join's structural asymmetry).
- TypeEnvironment bindings become Binding { ty: Rc<VariableType>,
  id: Cell<Option<u32>> } — the id is a lazily computed cache, invisible
  to the public API (equality still compares types only). meet_owned /
  outer_join / union all route through the memos; outer_join's
  collapse case keeps the left binding exactly as join(T, Zero) = T did.
- TypeEnvironment::union now takes the schema (checker + module tests
  updated).
- Kill switch GQLITE_DISABLE_TC_MEET_CACHE gates both memos;
  differential matrix extended (meet-off ≡ all-off row).

Idle-machine medians vs M07:
- subq_exists 22.9 → 15.6 us (−32%)   multi_optional 43.6 → 29.0 us (−33%)
- union_8     50.0 → 34.1 us (−32%)   union_4        20.8 → 16.6 us (−20%)
- chain_16    46.4 → 42.8 us (−8%)    (chains barely meet — expected)
- m07's anon_8 outlier confirmed as noise (back to 1.88 ms)

chk/parse now: trivial cases 0.69–0.95× (AT the north star), chains
2.3–4.2×, subq 4.1×, multi_optional 6.4×.

Cumulative vs session baseline: chain_16 10.5×, subq_exists 4.4×,
union_8 5.3×, multi_optional 4.0×, anon_16 ~5500×.

Full sweep 80 targets 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