Skip to content

Fix high CPU usage when encountering non-file URI workspaces #1396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 4, 2025

Conversation

thecrypticace
Copy link
Contributor

@thecrypticace thecrypticace commented Jun 2, 2025

Fixes #1394

There are two issues here:

  • Non-file schemes were being treated as if they were file:// URIs and we were getting their filesystem path when ends up being an empty string.
  • Neovim, when opening a virtual file (e.g. foo://bar.html), causes the server to be initialized with a file URI of file://. and rootPath of /.. I'd expect them to use the foo:// scheme but that does not happen. I think it's super reasonable to have the server refuse a workspace folder that is the filesystem root. This check is definitely not exhaustive (may not handle network shares, arbitrary mounts, different drives on Windows, etc…) but this is probably "good enough" to detect this situation.

Both of these results in the folder being treated as / and results in a file search from the root causing super high CPU usage. I've also added a check inside getProject so files with non-file schemes are ignored. They'll get a fsPath of empty string as well and as such won't match any project. The VSCode extension already does this at the extension level but we weren't doing it in the language server.

The VSCode extension itself already does this but the language server should as well
It’ll fail matching things *anyway* so we can just bail earlier
@thecrypticace thecrypticace changed the title Fix high CPU usage when encountering non-file-uri workspaces Fix high CPU usage when encountering non-file URI workspaces Jun 2, 2025
@thecrypticace
Copy link
Contributor Author

thecrypticace commented Jun 3, 2025

So I just did testing in a new Neovim 0.11 installation. This fix should still be applied to the language server because there is a bug here. But it will NOT fix the Neovim bug listed above. (addressed now)

For a virtual file foo://index.html Neovim is sending this initialization request to the server:

[DEBUG][2025-06-03 11:05:53] .../vim/lsp/rpc.lua:277	"rpc.send"	{
  id = 1,
  jsonrpc = "2.0",
  method = "initialize",
  params = {
    capabilities = { … },
    clientInfo = {
      name = "Neovim",
      version = "0.11.2+ga73904168a"
    },
    processId = 4238,
    rootPath = "/.",
    rootUri = "file://.",
    trace = "off",
    workDoneToken = "1",
    workspaceFolders = { {
        name = ".",
        uri = "file://."
      } }
  }
}

There's three things wrong here:

  • rootPath is /. which is wrong. For a non-file url I'm not sure that there is any valid value for this property.
  • rootUri should probably be foo://.
  • workspaceFolders.0.url should probably be foo://.

I think it's probably wrong for it to be file://. Ultimately this resolves to / according to vscode-uri:

const { URI } = await import("vscode-uri").then(m => m.default);
console.log(URI.parse('file://.').fsPath)
// logs `/`

From a normal initialization we get this:

  • Notice how all paths/URIs start in /Users/testing/Applications/test-project
[DEBUG][2025-06-03 11:14:08] .../vim/lsp/rpc.lua:277	"rpc.send"	{
  id = 1,
  jsonrpc = "2.0",
  method = "initialize",
  params = {
    capabilities = { … },
    clientInfo = {
      name = "Neovim",
      version = "0.11.2+ga73904168a"
    },
    processId = 839,
    rootPath = "/Users/testing/Applications/test-project",
    rootUri = "file:///Users/testing/Applications/test-project",
    trace = "off",
    workDoneToken = "1",
    workspaceFolders = { {
        name = "/Users/testing/Applications/test-project",
        uri = "file:///Users/testing/Applications/test-project"
      } }
  }
}

I'm thinking we could maybe check to see if fsPath resolves to / and either:

  • Hard fail (throw new Error(…))
  • Treat it as if the given workspace folders don't exist

Either way trying to run at a workspace folder root of / is pretty much guaranteed to cause problems.

@thecrypticace thecrypticace marked this pull request as ready for review June 3, 2025 16:11
@igorlfs
Copy link

igorlfs commented Jun 3, 2025

Hey,

There's three things wrong here:

  • rootPath is /. which is wrong. For a non-file url I'm not sure that there is any valid value for this property.
  • rootUri should probably be foo://.
  • workspaceFolders.0.url should probably be foo://.

I think it's probably wrong for it to be file://. Ultimately this resolves to / according to vscode-uri:

Thanks for the info. I'll open an issue in neovim.

@thecrypticace thecrypticace merged commit b6fbe32 into main Jun 4, 2025
12 checks passed
@thecrypticace thecrypticace deleted the fix/non-file-workspaces branch June 4, 2025 15:36
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.

High CPU usage with virtual files in neovim
2 participants