Skip to content

Too many workspaces are being opened for rust-analyzer #1778

@dimonomid

Description

@dimonomid

Hey there. First of all, thanks a lot for your work on this project! I use it pretty much daily and so it makes my life better every day, and overall I'm very happy with it.

These days I primarily use it for Rust. I used some old version until recently, but then I had to upgrade (since the Rust project our team works on has upgraded Rust and started using lock file version 4, which Rust coming with the old ycmd didn't support), and I noticed that rust-analyzer started to consume A TON more resources: so much that it's pretty much unbearable, very hard to get any work done this way, at least on my not-extremely-powerful Thinkpad.

What I found is that for every Rust crate I open, ycmd now apparently opens a new workspace in rust-analyzer, which in turn spawns a separate rust-analyzer-proc-macro-srv process etc. With the old ycmd, this wasn't happening: there wasn't even a concept of the workspace, and a particular instance of vim could only navigate to the code which the first Rust project I open has access to.

I understand that the introduction of workspaces is supposed to be an improvement, but unfortunately with the current implementation, it's not very usable. The main problem is that currently ycmd just opens way too many rust-analyzer workspaces.

I don't have a ready solution here, since I don't know enough about rust-analyzer and ycmd; and I'm sure you'll be able to arrive on a better solution that I can, but let me still share the issues that I've had, and some workarounds that I've done to unblock myself, in case it's helpful to find the right solution.

For example, we have a massive Rust project with many crates inside (about 300 atm). As I navigate code, I of course quickly open more and more of these crates, adding more and more rust-analyzer processes, each of which consumes a good chunk of CPU and RAM. And the thing is: all of these crates are actually being indexed by rust-analyzer with just a single workspace opened, there's no need to open a separate rust-analyzer workspace for every single sub-crate we have. So these extra rust-analyzer processes just do redundant work. So in an attempt to address this problem, I tried to add the following hack: in the GetWorkspaceForFilepath function, when looking for a dir containing Cargo.toml, instead of working our way up from the current file path, start from the root directory instead, and work our way down. I just hackishly added reverse(list(.....)) to this line. It did help to solve this particular part (with the many sub-crates), however there are other manifestations of the same problem:

Another manifestation is that as I navigate to the crates which are a part of stdlib, or fetched by Cargo, the same thing happens: for every crate, a new rust-analyzer workspace is being opened. And again it's not necessary: these crates are being indexed by the workspace which has access to them. To work around this issue, I've changed the GetProjectRootFiles to return rust-toolchain.toml instead of Cargo.toml, because our projects happen to have this rust-toolchain.toml at the root of the actual Rust workspace. In addition to that, since crates fetched by Cargo or which are part of stdlib don't have this file, I updated GetWorkspaceForFilepath to return None if the file not found, instead of just returning the path to the file.

Those two things unblock me so I can keep working now. For completeness, here's the hackish commit containing both of these changes, however I'm definitely not saying it should be merged in this form, or even close to that. Just sharing it to have the changes at a glance, in case it's helpful.

As I said above, I don't know what the right solution would be here. Thinking about it, I'd like to have something like this (no idea if rust-analyzer makes it possible though): whenever we open a new file, first check with rust-analyzer if the file is already indexed by any of the currently opened workspaces. If yes, then don't do anything, and just reuse the existing workspace. And only if the file is completely unreachable from any of the currently opened workspaces, then look for the Cargo.toml (and again, starting from the root dir, so that we use the biggest workspace possible, instead of using some sub-crate). I think this would be close to ideal: we do open multiple workspaces when working on multiple independent projects simultaneously, but we don't open redundant workspaces, so no resources are being wasted.

Last note fwiw, while bisecting, I found that the commit which introduces this problem is this one: Upgrade completers; so the concept of a workspace has already existed in ycmd, but I'm guessing rust-analyzer didn't support it before, and now it finally supports it, and the issues with how ycmd chooses workspaces have manifested now.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions