Skip to content

fix: stop CPU spikes in large monorepos - #130

Closed
omribarzik-gong wants to merge 2 commits into
vunguyentuan:masterfrom
omribarzik-gong:fix/cpu-spike-in-large-monorepos
Closed

omribarzik-gong wants to merge 2 commits into
vunguyentuan:masterfrom
omribarzik-gong:fix/cpu-spike-in-large-monorepos

Conversation

@omribarzik-gong

Copy link
Copy Markdown

The extension's live file watchers (**/*.css|scss|sass|less) never honored cssVariables.blacklistFolders - only the initial workspace scan did. Every matching fs event anywhere in the workspace (e.g. node_modules, dist, storybook-static during pnpm install/builds/git checkouts) reached the language server and triggered a synchronous postcss/less/scss parse.

On top of that, every batch of changes ran resolveAllVariableReferences() over the entire variable cache (not just the changed files), and onDidChangeConfiguration cleared the whole cache and re-scanned the workspace on any VS Code settings change, not just cssVariables.*.

In a monorepo with thousands of matching stylesheets, these three combined into sustained CPU spikes.

  • Filter onDidChangeWatchedFiles events against blacklistFolders before parsing (mirrors the existing fast-glob ignore behavior).
  • Debounce resolveAllVariableReferences so a burst of file events triggers one resolve pass instead of one per notification.
  • Skip the cache clear + full re-scan in onDidChangeConfiguration unless the resolved cssVariables settings actually changed.

The extension's live file watchers (**/*.css|scss|sass|less) never
honored cssVariables.blacklistFolders - only the initial workspace
scan did. Every matching fs event anywhere in the workspace (e.g.
node_modules, dist, storybook-static during pnpm install/builds/git
checkouts) reached the language server and triggered a synchronous
postcss/less/scss parse.

On top of that, every batch of changes ran resolveAllVariableReferences()
over the *entire* variable cache (not just the changed files), and
onDidChangeConfiguration cleared the whole cache and re-scanned the
workspace on any VS Code settings change, not just cssVariables.*.

In a monorepo with thousands of matching stylesheets, these three
combined into sustained CPU spikes.

- Filter onDidChangeWatchedFiles events against blacklistFolders
  before parsing (mirrors the existing fast-glob ignore behavior).
- Debounce resolveAllVariableReferences so a burst of file events
  triggers one resolve pass instead of one per notification.
- Skip the cache clear + full re-scan in onDidChangeConfiguration
  unless the resolved cssVariables settings actually changed.
@changeset-bot

changeset-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 517e376

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

blacklistFolders is a denylist and was already re-applied to the
watcher in the previous commit, but lookupFiles (the allowlist - e.g.
scoping the extension to only a handful of design-token files) was
still only consulted by the initial scan. Any changed file matching
the client's hardcoded **/*.css|scss|sass|less watchers still got
parsed and merged into the cache regardless of how narrow lookupFiles
was configured, silently growing scope back out over a session.

Add isIncludedFile(), mirroring fastGlob(lookupFiles, { ignore:
blacklistFolders, cwd }) exactly: dynamic glob patterns are filtered
by the blacklist, but an explicit static file path in lookupFiles
always matches regardless of the blacklist (verified against fast-glob
directly - it never applies `ignore` to non-dynamic patterns).
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