Skip to content

rust-analyzer analysis-stats doesn't respect excludeDirs #19779

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

Open
Logarithmus opened this issue May 11, 2025 · 13 comments
Open

rust-analyzer analysis-stats doesn't respect excludeDirs #19779

Logarithmus opened this issue May 11, 2025 · 13 comments
Labels
C-bug Category: bug

Comments

@Logarithmus
Copy link
Contributor

Logarithmus commented May 11, 2025

rust-analyzer version: rust-analyzer 1.87.0-nightly (4d30011 2025-03-15) (using old Salsa, because it uses 2 times less RAM)
rustc version: rustc 1.87.0-nightly (4d30011f6 2025-03-15)

editor or extension: LazyVim (nvim v0.11.0)

relevant settings:

rust-analyzer.json

{
  "rust-analyzer.cargo.features": [],
  "rust-analyzer.cargo.allTargets": false,
  "rust-analyzer.check.allTargets": false,
  "rust-analyzer.cfg.setTest": true,
  "rust-analyzer.checkOnSave": false,
  "rust-analyzer.cachePriming.enable": true,
  "rust-analyzer.files.excludeDirs": [
    "crates/db_diesel/src/schema.rs",
    "f2c/src/processing/withdrawal_flows/db/action/",
    "[redacted]..."
  ]
}

rust-analyzer.toml in workspace root

# Disables all inlay hints
[inlayHints]
typeHints.enable = false
parameterHints.enable = false
chainingHints.enable = false
closureReturnTypeHints.enable = false
bindingModeHints.enable = false
discriminantHints.enable = false
closureCaptureHints.enable = false

[references]
excludeImports = true

[files]
excludeDirs = [
  "crates/db_diesel/src/schema.rs",
  "f2c/src/withdrawals/db/action/",
  "[redacted]",
]

repository link (if public, optional): private

Expected behaviour: rust-analyzer skips lowering, type inference and trait solving for files and directories mentioned in files.excludeDirs

Actual behaviour:

6/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_processing_exchange::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_processing_exchange.rs 954..1715)    7694ms infer_query
      7270ms resolve_obligations_as_possible (444 calls)
        7266ms trait_solve_query @ detail = "SqlType"  (24 calls)
          7265ms solve  @ krate = Idx::<CrateData>(29) block = None  (24 calls)
8/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_processing_conversion::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_processing_conversion.rs 960..1786)    7674ms infer_query
      7252ms resolve_obligations_as_possible (444 calls)
        7247ms trait_solve_query @ detail = "SqlType"  (24 calls)
          7247ms solve  @ krate = Idx::<CrateData>(29) block = None  (24 calls)
70/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_preparing_withdrawal::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_preparing_withdrawal.rs 931..1690)   10054ms infer_query
      9704ms resolve_obligations_as_possible (439 calls)
        9701ms trait_solve_query @ detail = "AsExpression"  (16 calls)
          9701ms solve  @ krate = Idx::<CrateData>(29) block = None  (16 calls)
2/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_preparing_conversion::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_preparing_conversion.rs 931..1745)    9974ms infer_query
      9630ms resolve_obligations_as_possible (439 calls)
        9626ms trait_solve_query @ detail = "AsExpression"  (16 calls)
          9626ms solve  @ krate = Idx::<CrateData>(29) block = None  (16 calls)
4/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_failed::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_failed.rs 810..1230)    6486ms infer_query
      6413ms resolve_obligations_as_possible (352 calls)
        6410ms trait_solve_query @ detail = "AsExpression"  (15 calls)
          6410ms solve  @ krate = Idx::<CrateData>(29) block = None  (15 calls)
6/23404 7% processing: f2c::processing::withdrawal_flows::db::action::storage::update_deposited::handle (f2c/src/processing/withdrawal_flows/db/action/storage/update_deposited.rs 828..1255)
@Logarithmus Logarithmus added the C-bug Category: bug label May 11, 2025
@ChayimFriedman2
Copy link
Contributor

ChayimFriedman2 commented May 11, 2025

It's very possible indeed that we don't skip excludeDirs in analysis-stats, not all knobs have effect there. Do you have a specific need for it?

Edit: My mistake, no knob has effect there. settings.json is ignored with analysis-stats, and couldn't even work given it's a VSCode thing.

@Logarithmus
Copy link
Contributor Author

Logarithmus commented May 11, 2025

and couldn't even work given it's a VSCode thing.
It's not a "vscode thing". Normally I use Neovim with rustaceanvim plugin. For analysis-stats I don't use any editor obviously.

Maybe I can specify this config option in rust-analyzer.toml then? I have a global config in ~/.config/rust-analyzer/rust-analyzer.toml, can I create workspace-specific one?

Yes, I have a specific need for it: I want to benchmark and profile rust-analyzer analysis with and without diesel-related code, to see the difference. Using rust-analyzer analysis-stats is much simpler than re-starting neovim, opening the log, located in /tmp, etc. I want to abstract from LSP and editor specific stuff while benchmarking.

Anyway, I already determined that the culprit is shockingly slow chalk performance, but how hard would it be to implement excludeDirs for analysis-stats? Maybe I would make a PR.

My initial goal was to prevent rust-analyzer from using 100% of one core for infinitely long time, every time I open diesel-related code. So I've used analysis-stats and RA_PROFILE. And basically there are 3 options for now:

  1. rust-analyzer.files.excludeDirs, quick & dirty
  2. Improve chalk performance (hard, probably need several days just to get familiar with chalk internals).
  3. Optimized next-gen rustc trait solver (because for now it seems even slower than chalk) and help integrate it into rust-analyzer (superhuman-level-hard, but the best solution long-term). But it would require at least 1 year from now to polish the solver, stabilize it and port rust-analyzer to it, and I can't wait for a year or buy a supercomputer (many cores won't help much, since a lot of the time rust-analyzer is single-threaded)

@ChayimFriedman2
Copy link
Contributor

rust-analyzer.toml could theoretically work, but I don't know if we implemented it. Personally, if it's more than a couple lines change (I don't know), I wouldn't want to do this until the planned VFS rewrite. But maybe it already works, or is a minor change :)

Chalk performance is a problem, and hopefully the new trait solver (migration soon-ish) will improve that. Chalk wasn't optimized at all, while the new trait solver will be used in rustc, so will get heavy optimization.

Also note that analysis-stats doesn't replicate a typical IDE workflow; it surely benchmarks how long it takes the analyze a project, but it runs inference on all functions in the project, while during usual workflow we only infer a couple. rust-analyzer gains its performance from incrementality, not raw performance (although of course this is also a factor). We know we can improve wrt. incrementality too, though.

@Logarithmus
Copy link
Contributor Author

Logarithmus commented May 11, 2025

@ChayimFriedman2 By the way about single-threadness, I've noticed that I can pass --parallel flag to analysis-stats and then trait solving becomes parallel. But when I used rust-analyzer in the editor, without excludeDirs, but with cachePriming: false, and open database (diesel) code, rust-analyzer starts to use just single thread indefinitely. So I've learned to just restart the editor if I accidentally jump into diesel db schema or other related files. And open db schema by nvim --noplugin.

Fortunately, with excludeDirs, my development experience will be less annoying :) By the way, according to rust-analyzer book, it should be files.exclude, not files.excludeDirs, but the former didn't work for me.

@Logarithmus
Copy link
Contributor Author

Is there any way to learn if rust-analyzer analysis-stats loaded rust-analyzer.toml or not?

@ChayimFriedman2
Copy link
Contributor

I don't understand, do you want excludeDirs for your IDE work (it's already available there) or for analysis-stats?

About parallelism, yes, this is because when the --parallel flag is passed analysis-stats infers functions in parallel, but in IDE, different requests (e.g. completions and semantic highlighting) are executed in parallel, but parallelism within a request is very limited. This is also something we wish to improve, and something that was unblocked by the Salsa 3 migration.

@ChayimFriedman2
Copy link
Contributor

Also, you might be misunderstanding what excludeDirs does: it makes r-a ignore those files, as if they don't exist. That means that not only requests inside the files won't be handled, but also e.g. if the code in those files defines some API, r-a won't know about it at all, and won't complete/hover it etc., even in other files.

@ChayimFriedman2
Copy link
Contributor

Is there any way to learn if rust-analyzer analysis-stats loaded rust-analyzer.toml or not?

Try and see?

@Logarithmus
Copy link
Contributor Author

Logarithmus commented May 11, 2025

@ChayimFriedman2 excludeDirs already work in nvim, I've tested it and happy with the result.

I thought it would work for analysis-stats, since it will greatly simplify benchmarking chalk optimizations (I could exclude all db files except one or two), if I'll find time and make those optimizations. Maybe there are some low hanging fruits...

Thank you for such quick and helpful response. Will keep issue open for now, I think

@ChayimFriedman2
Copy link
Contributor

I wouldn't recommend investing time/work in trying to optimize chalk. As I said, we expect to switch soon-ish to the next trait solver (jackh726 is working on that), so any work done on chalk will be lost.

@Logarithmus
Copy link
Contributor Author

@ChayimFriedman2 makes sense. I will use excludeDirs workaround for now, and investigate how to speed up nextgen solver. Because currently it can't compile our db_diesel crate at all, giving resursion limit error after several minutes of thinking.

@Logarithmus
Copy link
Contributor Author

I've just tested analysis-stats with excludeDirs in rust-anayzer.toml. Unfortunately, it didn't change anything. It's low-priority, but would be nice to have

@xiaguangbo
Copy link

1

./rust-analyzer-2025-05-12 analysis-stats /home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project/
Error: Failed to load the project at /home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project/Cargo.toml

Caused by:
    0: Failed to read Cargo metadata from Cargo.toml file /home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project/Cargo.toml, Some(Version { major: 1, minor: 87, patch: 0 })
    1: Failed to run `cd "/home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project" && RUSTUP_TOOLCHAIN="/home/xiaguangbo/.rustup/toolchains/stable-x86_64-unknown-linux-gnu" "/home/xiaguangbo/.cargo/bin/cargo" "metadata" "--format-version" "1" "--manifest-path" "/home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project/Cargo.toml" "--filter-platform" "thumbv6m-none-eabi"`
    2: `cargo metadata` exited with an error: error: failed to parse manifest at `/home/xiaguangbo/linux/project/electric_stunning/program_rp2040/project/Cargo.toml`

       Caused by:
         binary target bin.name is required


Stack backtrace:
   0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
   1: project_model::cargo_workspace::CargoWorkspace::fetch_metadata_
   2: project_model::cargo_workspace::CargoWorkspace::fetch_metadata
   3: std::sys::backtrace::__rust_begin_short_backtrace
   4: core::ops::function::FnOnce::call_once{{vtable.shim}}
   5: std::sys::pal::unix::thread::Thread::new::thread_start
   6: start_thread
   7: __clone3

2

in Cargo.toml add

[[bin]]
name = "project"

bin.name and package.name same

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

3 participants