Skip to content

perf: micro-optimizations in hot paths#2960

Merged
jasonlyu123 merged 6 commits intosveltejs:masterfrom
MathiasWP:perf/micro-optimizations-hot-paths
Mar 14, 2026
Merged

perf: micro-optimizations in hot paths#2960
jasonlyu123 merged 6 commits intosveltejs:masterfrom
MathiasWP:perf/micro-optimizations-hot-paths

Conversation

@MathiasWP
Copy link
Contributor

@MathiasWP MathiasWP commented Feb 26, 2026

Summary

  • Replace O(n²) flatten() with Array.prototype.flat() — the existing reduce+spread implementation copies the accumulator on every iteration. Called from DiagnosticsProvider, CompletionProvider, FindReferencesProvider, CodeActionsProvider, and more
  • Remove lodash flatten from PluginHost — replaces ~10 flatten(...) call sites with .flat(). PluginHost is the central dispatch for all LSP operations
  • Use Object.create(node) instead of { ...node } in svelteNodeAt — avoids copying all AST node properties on every matching ancestor while walking the tree. Called from completions, diagnostics, rename, and semantic tokens
  • Cache getExistingImports per document URI + version — avoids re-parsing all imports via regex on every completion request
  • Early return + RegExp.test() in isExistingSvelteComponentImport — avoids allocating a match array for every Svelte component completion item
  • Replace possiblyComponent regex with charCode comparison — regex is overkill for checking a single ASCII uppercase character
  • Fix lineCount to use cached line offsets — was splitting the entire document text on every call when getLineOffsets() is already cached
  • Optimize getByPrefix to iterate without intermediate array — push loop instead of Array.from + filter + map chain
  • Optimize logStatistics to single-pass counting — replaces Set→Array conversion and double .filter() with a single loop

Test plan

  • All 664 existing tests pass (8 pending, 0 failing)
  • Clean build with pnpm build
  • Manual smoke test: open a Svelte project, verify completions, hover, diagnostics, and rename work correctly

🤖 Generated with Claude Code

…gnostics

Replace O(n²) flatten() with Array.prototype.flat(), remove lodash flatten
dependency from PluginHost, use Object.create instead of object spread in
svelteNodeAt AST walking, cache getExistingImports per document, use
RegExp.test() over .match(), replace regex with charCode check in
possiblyComponent, use cached line offsets for lineCount, and optimize
iteration in SnapshotManager.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

🦋 Changeset detected

Latest commit: eb6b785

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte-language-server Patch

Not sure what this means? Click here to learn what changesets are.

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

MathiasWP and others added 3 commits February 26, 2026 16:22
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MathiasWP and others added 2 commits March 2, 2026 11:48
- Replace all flatten() call sites with .flat()/.flatMap() and remove
  the flatten utility function entirely
- Use charCodeAt(0) directly in possiblyComponent instead of char comparison
- Use block syntax for single-line for loops in SnapshotManager
- Remove ineffective existingImportsCache from CompletionProvider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@MathiasWP MathiasWP requested a review from jasonlyu123 March 2, 2026 10:51
@jasonlyu123 jasonlyu123 merged commit 11bc4bc into sveltejs:master Mar 14, 2026
3 checks passed
@github-actions github-actions bot mentioned this pull request Mar 14, 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.

2 participants