I have recently been on a quest to get more speed from my Rust development environment, and today’s “why is this so fscking slow!” culprit is rust-analyzer.A larger project like delta-rs benefits from IDE-like machinery to help work across a sprawling codebase written in Python and Rust. rust-analyzer helps greatly with that, but it comes with a speed penalty.
The tool aims to:
Bringing a great IDE experience to the Rust programming language
When used with rustacean.vim in my Neovim configuration I get inline rustdocs, syntax validation as I type, and a suite of other helpful tools, but it comes with a speed penalty.
Opening a single large lib.rs
file typically means a rust-analyzer
process is spun up in the background which is effectively parses the Rust
file(s) in scope and produces the necessary information to provide Language
Server Protocol (LSP) responses to Neovim. This compilation sits on top of the
existing project’s compilation, which could be good. It could be good in
other projects, but not quite for delta-rs where we have a menagerie of
different crates and build patterns.
Switching to build the Python always resulted in a full recompile.
Building the Rust-only crates didn’t cause that behavior, but something about
our Python package always caused a full recompile when switching between my
editor and the make
invocations to build the package.
Savvy rust developers may have a hunch on the problem already: if RUSTFLAGS are
changed, the entire build is effectively tainted by cargo
and must be
recompiled.
make
has one set of flags. rust-analyzer
has another set. Never the twain
shall meet.
Trying to find an way to rectify this situation I stumbled into the
rust-analyzer
configuration where
I discovered the cargo.targetDir
directory.
I also discovered this tidbit deep in the README for rustacean.vim
:
. By default, this plugin will look for a .vscode/settings.json
file and
attempt to load it. If the file does not exist, or it can’t be decoded, the server.default_settings will be used.
It can’t be that simple can it?
I introduced a .vscode/settings.json
into my local working directory with the
following snippet, which will cause rust-analyzer
to use its own target
directory inside the existing target/
:
{"rust-analyzer.cargo.targetDir" : true }
The trade-off is that instead of a speed penalty, there is a disk storage
penalty as redundant copies of compiled objects are stored in target/
. In my
situation the compile time seed switching between my editor and the
unit/integration tests is far more valuable than a few extra gigabytes (oof)
on disk.
Even with this improvement, I still have a need.
A need for speed.