Repository navigation
perf(query): lazy-load the MCPServer re-export (14% faster query startup) - #2920
Closed
johnhldiver-beep wants to merge 1 commit into
Closed
johnhldiver-beep wants to merge 1 commit into
johnhldiver-beep wants to merge 1 commit into
Conversation
`src/index.ts` statically re-exported MCPServer from './mcp', so every consumer of the entry -- including `codegraph query` through loadCodeGraph() -- pulled the whole MCP server module graph (daemon, proxy, engine, session, writer-lock, tools) into startup, though no query path touches it. Replace the static re-export with a lazy getter: the same value and type surface, the same ESM named-export interop (the getter is written in the exact shape cjs-module-lexer recognizes), and `./mcp` loads on first access. `mcp/version` stays eager (dependency-free, used by indexAll()). A/B benchmark (n=30, alternating): shipped query mean 3454ms -> 2957ms (-14.4%); single process 3026ms -> 2538ms (-16.1%); module graph 252 -> 227. Numbers and method in docs/benchmarks/query-startup-lazy-mcp.md. New tests lock in the laziness contract from CJS, ESM and the spawned CLI.
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.
Summary
src/index.tsre-exportedMCPServerstatically, so every consumer of the package entry — includingcodegraph query, which reaches the entry throughloadCodeGraph()— paid for the whole MCP server module graph (daemon, proxy, engine, session, writer-lock, the 8.3k-linetoolsmodule) at startup, although no query path touches it.This makes the re-export lazy:
./mcpis loaded by a CommonJS getter on first access toMCPServer. The value, the type surface (export const+export type), and the ESM named-export interop are unchanged;cjs-module-lexerinterop is preserved because the getter is emitted in the exact shapetscuses for a static re-export.mcp/versionstays eager — it is dependency-free andindexAll()records the package version into the index.codegraph serve/the daemon already usedawait import('../mcp/index'), and there were no internal call sites for the re-export.Benchmark
Full method, before/after tables and module counts:
docs/benchmarks/query-startup-lazy-mcp.md. A/B alternating runs, n=30 per build, shared machine:query "Handler" --json)CODEGRAPH_WASM_RELAUNCHED=1)Module graph of a query run: 252 → 227 modules (−25);
require('dist/index.js'): 236 (26mcp/*) → 199 (1mcp/*).Tests
npx tsc --noEmit— clean.npm run build— clean.__tests__/lazy-mcp-export.test.ts(3 tests) pins the contract: nothing from the MCP server graph loads untilMCPServeris touched, the lazy value is identical todist/mcp's class, ESMimport { MCPServer }still works, and a spawnedcodegraph queryloads only the CLI's small support modules. The two laziness tests fail against a build of the pre-change source. Together withdefault-export-declarationandcli-index-explicit-path: 12/12.npm test: 748/766 files passed, 17 skipped; 8557 tests passed, 408 skipped. One file (react-router.test.ts) hit abeforeAllhook timeout under the 4-worker parallel run while the OS watch/file limit was exhausted (File watcher disabled … too many open files); it passes 70/70 when re-run alone, and is unrelated to this change.Related: dependency upgrades in #2885,
mcp/query-poolin #2862 andinitin #2888 are separate efforts; nothing here overlaps them.