Skip to content

perf(typescript-language): memoize deterministic native checker queries - #3418

Draft
JoshuaKGoldberg wants to merge 3 commits into
typescript-7-1-nativefrom
perf/checker-query-memoization
Draft

JoshuaKGoldberg wants to merge 3 commits into
typescript-7-1-nativefrom
perf/checker-query-memoization

Conversation

@JoshuaKGoldberg

@JoshuaKGoldberg JoshuaKGoldberg commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Draft — memoization of the out-of-process native checker.

The TS7 native checker runs out-of-process, so every getTypeAtLocation /
getSymbolAtLocation / etc. is an IPC round-trip. Type-aware rules frequently
query the same node/type/symbol, so wrapping the checker to memoize each
deterministic query by argument identity (for the life of the stable snapshot)
collapses those repeats. Extracted into memoizedChecker.ts and extended from
the original 6-method set to every deterministic query rules call:

  • single-arg identity: getTypeAtLocation, getSymbolAtLocation,
    getApparentType, getBaseConstraintOfType, getTypeArguments,
    getTypeOfSymbol, isArrayType, isTupleType, getAliasedSymbol,
    getImmediateAliasedSymbol, getContextualType, getResolvedSignature,
    getShorthandAssignmentValueSymbol, getTypeFromTypeNode, typeToString
    (only when called with exactly one argument, so option-bearing overloads
    fall through uncached)
  • two-arg identity: getTypeOfSymbolAtLocation, isTypeAssignableTo

Measured (hyperfine, --cache-ignore --skip-formatting --skip-language-reports)

End-to-end vs no memoization:

files × rules no memo this PR delta
256 × 272 961 ms 859 ms −10.6%
1024 × 119 2.498 s 2.344 s −6.2%
1024 × 272 3.084 s 2.723 s −11.7%

The extended method set adds ~1% over the original 6-method version — small but
consistent across scales and free (correctness verified: identical report
output). Report parity confirmed against the raw checker.

🤖 Generated with Claude Code

The native checker runs out-of-process, so each getTypeAtLocation /
getSymbolAtLocation is an IPC round-trip. Many type-aware rules query the same
node, so wrap the shared checker in a per-snapshot memoizing proxy (WeakMap
keyed by node identity) to collapse those repeats to one round-trip. Results are
stable while the snapshot is unchanged (the whole visitor phase).

Measured (hyperfine, ESLint-anchored): ~6% faster at high files x many rules
(1024 files/272 rules: 2.977s -> 2.855s; 256/272: 922ms -> 868ms), neutral
elsewhere. Targets the residual where TS7's per-rule checker IPC trails TS6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcCVWAfhF3shCsdz2niEFi
@changeset-bot

changeset-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 9d53dc7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@netlify

netlify Bot commented Sep 8, 2026

Copy link
Copy Markdown

Deploy Preview for flint-fyi failed.

Name Link
🔨 Latest commit 9d53dc7
🔍 Latest deploy log https://app.netlify.com/projects/flint-fyi/deploys/6a9f68973dfd49000817a2f9

@pkg-pr-new

pkg-pr-new Bot commented Sep 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

@flint.fyi/astro

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/astro@9d53dc7 -D

@flint.fyi/astro-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/astro-language@9d53dc7 -D

@flint.fyi/browser

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/browser@9d53dc7 -D

@flint.fyi/cli

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/cli@9d53dc7 -D

@flint.fyi/content-mapper

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/content-mapper@9d53dc7 -D

@flint.fyi/core

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/core@9d53dc7 -D

@flint.fyi/css

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/css@9d53dc7 -D

@flint.fyi/css-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/css-language@9d53dc7 -D

flint

pnpm add https://pkg.pr.new/flint-fyi/flint@9d53dc7 -D

@flint.fyi/json

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/json@9d53dc7 -D

@flint.fyi/json-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/json-language@9d53dc7 -D

@flint.fyi/jsx

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/jsx@9d53dc7 -D

@flint.fyi/markdown-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/markdown-language@9d53dc7 -D

@flint.fyi/md

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/md@9d53dc7 -D

@flint.fyi/next

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/next@9d53dc7 -D

@flint.fyi/node

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/node@9d53dc7 -D

@flint.fyi/nuxt

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/nuxt@9d53dc7 -D

@flint.fyi/package-json

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/package-json@9d53dc7 -D

@flint.fyi/performance

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/performance@9d53dc7 -D

@flint.fyi/plugin-flint

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/plugin-flint@9d53dc7 -D

@flint.fyi/react

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/react@9d53dc7 -D

@flint.fyi/rule-data

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/rule-data@9d53dc7 -D

@flint.fyi/rule-tester

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/rule-tester@9d53dc7 -D

@flint.fyi/solid

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/solid@9d53dc7 -D

@flint.fyi/spelling

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/spelling@9d53dc7 -D

@flint.fyi/svelte

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/svelte@9d53dc7 -D

@flint.fyi/svelte-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/svelte-language@9d53dc7 -D

@flint.fyi/text-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/text-language@9d53dc7 -D

@flint.fyi/ts

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/ts@9d53dc7 -D

@flint.fyi/ts-patch

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/ts-patch@9d53dc7 -D

@flint.fyi/typescript-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/typescript-language@9d53dc7 -D

@flint.fyi/utils

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/utils@9d53dc7 -D

@flint.fyi/vitest

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/vitest@9d53dc7 -D

@flint.fyi/vue

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/vue@9d53dc7 -D

@flint.fyi/vue-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/vue-language@9d53dc7 -D

@flint.fyi/yaml

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/yaml@9d53dc7 -D

@flint.fyi/yaml-language

pnpm add https://pkg.pr.new/flint-fyi/flint/@flint.fyi/yaml-language@9d53dc7 -D

commit: 9d53dc7

JoshuaKGoldberg and others added 2 commits September 7, 2026 20:53
…queries

Also memoize getTypeOfSymbol, getTypeArguments, getApparentType,
getBaseConstraintOfType, isArrayType, isTupleType by their Type/Symbol argument
identity. These deterministic-per-snapshot queries are called heavily by
type-aware rules; caching them roughly doubles the dedup win at high files x
rules (1024/272: -6% -> -10.6% vs baseline).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcCVWAfhF3shCsdz2niEFi
Extends the memoized checker to every deterministic query rules call
(aliased-symbol, contextual type, resolved signature, typeToString,
type-from-node, and the two-arg getTypeOfSymbolAtLocation /
isTypeAssignableTo), keyed by argument identity. Extracts the wrapper
into memoizedChecker.ts. Measured ~1% beyond the prior six-method set and
11-12% over no memoization at 1024 files x 272 rules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcCVWAfhF3shCsdz2niEFi
@JoshuaKGoldberg JoshuaKGoldberg changed the title perf: memoize checker node queries per snapshot perf(typescript-language): memoize deterministic native checker queries Sep 8, 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.

1 participant