Repository navigation
[api] Client performance optimizations - #64823
Open
Andrew Branch (andrewbranch) wants to merge 6 commits into
Open
Andrew Branch (andrewbranch) wants to merge 6 commits into
Andrew Branch (andrewbranch) wants to merge 6 commits into
Conversation
createChildren allocated a fresh scanner for every node whose children were materialized, and the token lookups (getTokenAtPosition, findNextToken, findPrecedingToken) allocated one per query. Keep a per-source-file pool of idle scanners (WeakMap<SourceFile, Scanner[]>): check out by popping or creating, reset text/language variant on checkout, and in a finally block clear comment directives and token state before returning the scanner. Scanners are removed from the pool while in use, so nested or reentrant traversals always get distinct scanners. Add tests covering reuse across cached/repeated calls and token lookups, nested child creation, exceptions during child creation, trivia/comment directives/JSDoc state, exact token boundaries, and independent source files with different language variants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit acac55e)
encoding/json/v2 only omits empty JSON values for omitempty, so every TypeResponse carried "objectFlags":0, "isTupleType":false, "value":null and "isThisType":false, every SymbolResponse "checkFlags":0, and every SignatureResponse "flags":0. Use omitzero and default the fields on the client. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 4551280)
Give projects a server-generated numeric identity preserved across snapshot clones. Resolve request handles directly through a lazily initialized index owned by each snapshot project collection, rather than a process-wide alias-to-path table. Keep public logical project IDs unchanged. Use typed numeric handles in request parameters, symbol owners, and project-scoped registries; regenerate both API clients and remove the custom JSON alias decoder. Cover snapshot isolation, cloning, removal and recreation, concurrent lookup, and omission of project identity from file-owned symbol responses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the existing source-file node ID and node-table index as node identity. Client requests send "index.#sourceFileID"; server responses retain kind and path as "index.kind.#sourceFileID.path". Resolve request handles through a lazy index owned by the program. Remove the process-global ID-to-path registry and reject nodes from another AST, even when the path and text match. Client response handles verify the AST identity before resolving a node fetched by path. Cover shared ASTs, stale and separately parsed files, malformed requests, response metadata, and concurrent source-file identity lookup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Symbols and signatures parsed every declaration handle into a NodeHandle as soon as they were received, although most are never read. Keep the wire strings and create the NodeHandles when declarations, valueDeclaration, or declaration is first accessed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit c5f5be5)
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Cross-language protocol and AST-identity changes warrant human review and full API validation, which was not run here.
0 open findings
What changed in this PR
Optimizes the TypeScript API clients by reducing allocations and protocol overhead while making project and node identities explicit.
Changes:
- Introduces numeric project handles and compact, exact-AST node request handles.
- Lazily creates declaration handles, omits zero-valued response fields, and pools scanners.
- Adds identity, stale-handle, concurrency, and scanner-reuse tests.
| File | Description |
|---|---|
| tsc/internal/project/projecthandle_test.go | Tests handle lifetime and concurrent lookup. |
| tsc/internal/project/projectcollection.go | Adds cached project-handle lookup. |
| tsc/internal/project/project.go | Assigns lifetime-stable project handles. |
| tsc/internal/json/json.go | Exposes the JSON options type. |
| tsc/internal/compiler/program.go | Indexes source files by node identity. |
| tsc/internal/api/session.go | Uses project handles and exact-AST node lookup. |
| tsc/internal/api/session_symbolresponse_test.go | Updates symbol ownership serialization tests. |
| tsc/internal/api/session_requestfilesystem_test.go | Uses handles in filesystem tests. |
| tsc/internal/api/session_module_resolution_test.go | Uses handles in resolution tests. |
| tsc/internal/api/session_createprogram_test.go | Uses handles in program tests. |
| tsc/internal/api/session_completion_test.go | Uses handles in completion tests. |
| tsc/internal/api/session_batch_test.go | Updates batched request payloads. |
| tsc/internal/api/session_apistate_test.go | Tests handle stability and snapshot scope. |
| tsc/internal/api/proto.go | Updates handles and omits zero-valued fields. |
| tsc/internal/api/projecthandle_test.go | Tests numeric handles and snapshot isolation. |
| tsc/internal/api/nodehandle_test.go | Tests exact-AST lookup and invalid handles. |
| packages/typescript/test/sync/ast.test.ts | Tests scanner pooling and state cleanup. |
| packages/typescript/test/sync/api.test.ts | Tests synchronous exact-AST behavior. |
| packages/typescript/test/sync/api-generators.test.ts | Updates node-handle equivalence checks. |
| packages/typescript/test/proto.test.ts | Updates numeric ownership fixtures. |
| packages/typescript/test/path.test.ts | Tests the revised node-handle format. |
| packages/typescript/test/async/api.test.ts | Tests asynchronous exact-AST behavior. |
| packages/typescript/src/ast/astnav.ts | Pools scanners for AST navigation. |
| packages/typescript/src/api/sync/api.ts | Updates generated synchronous client behavior. |
| packages/typescript/src/api/proto.ts | Uses numeric symbol-owner project handles. |
| packages/typescript/src/api/proto.generated.ts | Updates generated protocol types. |
| packages/typescript/src/api/node/node.ts | Parses exact-AST handles and emits compact requests. |
| packages/typescript/src/api/async/api.ts | Updates requests and lazily creates declaration handles. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Update the circular-extends regression test added on main to pass the project's lifetime handle to the diagnostics request instead of its logical ID. This fixes the merged PR's test-package compilation failure across test and lint jobs. Validation: npx hereby validate --all; targeted API race tests; noembed API tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Andrew Branch (andrewbranch)
requested review from
Jake Bailey (jakebailey) and
Wesley Wigham (weswigham)
October 15, 2026 00:39
| pool.push(scanner); | ||
| } | ||
|
|
||
| function withScanner<T>(sourceFile: SourceFile, pos: number | undefined, callback: (scanner: Scanner) => T): T { |
There was a problem hiding this comment.
If you wanted to be extra clever, you could use using
| } | ||
|
|
||
| type ( | ||
| Options = json.Options |
There was a problem hiding this comment.
I think this is unused
This branch has not been deployed
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.
Five independent changes, best viewed one commit at a time.
This reduces wall clock time for the recommended ruleset over 1024 files in https://github.com/typescript-eslint/performance by 4.9% on my machine, with 61% fewer allocations from the client. Retained heap falls by 1.4%. Most of the allocation reduction is from 47fddf5.
The batched
getSymbolAtLocationbenchmark from our own suite is also 28% faster in the async client and 22% faster in the sync client.