[ty] Parallelize workspace symbols

This is a pretty naive approach, but it makes cold times for listing
workspace symbols in home-assistant under 1s on my machine.

Courtesy of Micha:
https://github.com/astral-sh/ruff/pull/20030#discussion_r2292924171
This commit is contained in:
Andrew Gallant 2025-08-22 09:07:30 -04:00 committed by Andrew Gallant
parent fb2d0af18c
commit f407f12f4c
3 changed files with 26 additions and 13 deletions

1
Cargo.lock generated
View file

@ -4243,6 +4243,7 @@ dependencies = [
"bitflags 2.9.2",
"insta",
"itertools 0.14.0",
"rayon",
"regex",
"ruff_db",
"ruff_memory_usage",

View file

@ -23,6 +23,7 @@ ty_python_semantic = { workspace = true }
ty_project = { workspace = true, features = ["testing"] }
itertools = { workspace = true }
rayon = { workspace = true }
regex = { workspace = true }
rustc-hash = { workspace = true }
salsa = { workspace = true, features = ["compact_str"] }

View file

@ -10,7 +10,6 @@ pub fn workspace_symbols(db: &dyn Db, query: &str) -> Vec<WorkspaceSymbolInfo> {
return Vec::new();
}
let mut results = Vec::new();
let project = db.project();
let options = SymbolsOptions {
@ -19,22 +18,34 @@ pub fn workspace_symbols(db: &dyn Db, query: &str) -> Vec<WorkspaceSymbolInfo> {
query_string: Some(query.into()),
};
// Get all files in the project
let files = project.files(db);
let results = std::sync::Mutex::new(Vec::new());
{
let db = db.dyn_clone();
let files = &files;
let options = &options;
let results = &results;
// For each file, extract symbols and add them to results
for file in files.iter() {
let file_symbols = symbols_for_file(db, *file, &options);
for symbol in file_symbols {
results.push(WorkspaceSymbolInfo {
symbol: symbol.clone(),
file: *file,
});
}
rayon::scope(move |s| {
// For each file, extract symbols and add them to results
for file in files.iter() {
let db = db.dyn_clone();
s.spawn(move |_| {
for symbol in symbols_for_file(&*db, *file, options) {
// It seems like we could do better here than
// locking `results` for every single symbol,
// but this works pretty well as it is.
results.lock().unwrap().push(WorkspaceSymbolInfo {
symbol: symbol.clone(),
file: *file,
});
}
});
}
});
}
results
results.into_inner().unwrap()
}
/// A symbol found in the workspace, including the file it was found in.