Skip to content

Conversation

@DanielFabian
Copy link
Member

Fix: Optimize inline code symbol linkifier to avoid redundant file I/O

The inline code linkifier (InlineCodeSymbolLinkifier) was causing severe performance issues during LLM response streaming. For each backticked symbol (e.g., TextDocument), it would re-read every reference file from disk, resulting in O(N×M) file reads where N = symbol count and M = reference count.

Changes:

  • Language gating: Skip files entirely when tree-sitter doesn't support their language (.log, .md, .json, etc.) in symbolMatchesOnly mode—zero I/O for unsupported files.

  • Document cache: Add a per-resolver documentCache so each file is read at most once per response, reducing file reads from O(N×M) to O(M).

Impact: Responses with many backticked symbols and large context files (especially non-code files like logs) should no longer hang the UI. Should help with microsoft/vscode#275716

Copilot AI review requested due to automatic review settings November 26, 2025 12:37
Copilot finished reviewing on behalf of DanielFabian November 26, 2025 12:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the inline code symbol linkifier to address severe performance issues during LLM response streaming. The linkifier was performing O(N×M) file reads (N = backticked symbols, M = reference files) by re-reading every file for each symbol. The PR implements two key optimizations:

  • Language gating: Skip files entirely when their language isn't supported by tree-sitter in symbolMatchesOnly mode
  • Document caching: Add per-resolver document cache to ensure each file is read at most once per response


export class ReferencesSymbolResolver {
/** Symbols which we have already tried to resolve */
private readonly cache = new Map<string, Promise<vscode.Location[] | undefined>>();
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider adding a JSDoc comment to document the purpose of the documentCache field. For example:

/** Cache of documents read during symbol resolution to avoid redundant file I/O within a single response. */
private readonly documentCache = new Map<string, Promise<SimpleTextDocument | undefined>>();

This would help future maintainers understand that the cache is per-resolver instance (and thus per-response) and is meant to avoid reading the same file multiple times during linkification of a single response.

Suggested change
private readonly cache = new Map<string, Promise<vscode.Location[] | undefined>>();
private readonly cache = new Map<string, Promise<vscode.Location[] | undefined>>();
/**
* Cache of documents read during symbol resolution to avoid redundant file I/O within a single response.
* This cache is per-resolver instance (and thus per-response) and is meant to avoid reading the same file
* multiple times during linkification of a single response.
*/

Copilot uses AI. Check for mistakes.
@connor4312 connor4312 assigned mjbvz and unassigned connor4312 Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants