Auto merge of #153131 - Kobzol:filesearch-opt, r=nnethercote

Optimize dependency file search

I tried to look into the slowdown reported in https://github.com/rust-lang/cargo/issues/16665.

I created a Rust hello world program, and used this Python script to create a directory containing 200k files:
```python
from pathlib import Path

dir = Path("deps")
dir.mkdir(parents=True, exist_ok=True)
for i in range(200000):
    path = dir / f"file{i:07}.o"
    with open(path, "w") as f:
        f.write("\n")
```

Then I tried to do various small microoptimalizations and simplifications to the code that iterates the search directories. Each individual commit improved performance, with the third one having the biggest effect.

Here are the results on `main` vs the last commit with the stage1 compiler on Linux, using `hyperfine "rustc +stage1 src/main.rs -L deps" -r 30` (there's IO involved, so it's good to let it run for a while):

```bash
Benchmark 1: rustc +stage1 src/main.rs -L deps
  Time (mean ± σ):     299.4 ms ±   2.7 ms    [User: 161.9 ms, System: 144.9 ms]
  Range (min … max):   294.8 ms … 307.1 ms    30 runs

Benchmark 1: rustc +stage1 src/main.rs -L deps
  Time (mean ± σ):     208.1 ms ±   4.5 ms    [User: 87.3 ms, System: 128.7 ms]
  Range (min … max):   202.4 ms … 219.6 ms    30 runs
```

Would be cool if someone could try this on macOS (maybe @ehuss - not sure if you have macOS or you only commented about its behavior on the Cargo issue :) ).

I also tried to prefilter the paths (not in this PR); right now we load everything and then we filter files with given prefixes, that's wasteful. Filtering just files starting with `lib` would get us down to ~150ms here. (The baseline without `-L` is ~80ms on my PC). The rest of the 70ms is essentially allocations from iterating the directory entries and sorting. That would be very hard to change - iterating the directory entries (de)allocates a lot of intermediate paths :( We'd have to implement the iteration by hand with either arena allocation, or at least some better management of memory.

r? @nnethercote
tree: 11c15f88ee9e79d97f1c45afa0b7354725cd33e5
  1. .cargo/
  2. .github/
  3. .vscode/
  4. assets/
  5. bench_data/
  6. crates/
  7. docs/
  8. editors/
  9. lib/
  10. xtask/
  11. .editorconfig
  12. .git-blame-ignore-revs
  13. .gitattributes
  14. .gitignore
  15. .typos.toml
  16. Cargo.lock
  17. Cargo.toml
  18. clippy.toml
  19. CONTRIBUTING.md
  20. josh-sync.toml
  21. LICENSE-APACHE
  22. LICENSE-MIT
  23. PRIVACY.md
  24. README.md
  25. rust-version
  26. rustfmt.toml
  27. triagebot.toml
README.md

rust-analyzer is a language server that provides IDE functionality for writing Rust programs. You can use it with any editor that supports the Language Server Protocol (VS Code, Vim, Emacs, Zed, etc).

rust-analyzer features include go-to-definition, find-all-references, refactorings and code completion. rust-analyzer also supports integrated formatting (with rustfmt) and integrated diagnostics (with rustc and clippy).

Internally, rust-analyzer is structured as a set of libraries for analyzing Rust code. See Architecture in the manual.

Quick Start

https://rust-analyzer.github.io/book/installation.html

Documentation

If you want to contribute to rust-analyzer check out the CONTRIBUTING.md or if you are just curious about how things work under the hood, see the Contributing section of the manual.

If you want to use rust-analyzer's language server with your editor of choice, check the manual. It also contains some tips & tricks to help you be more productive when using rust-analyzer.

Security and Privacy

See the security and privacy sections of the manual.

Communication

For usage and troubleshooting requests, please use “IDEs and Editors” category of the Rust forum:

https://users.rust-lang.org/c/ide/14

For questions about development and implementation, join rust-analyzer working group on Zulip:

https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer

Quick Links

License

rust-analyzer is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.