10743: feat: index fewer crates on startup/reload r=jonas-schievink a=jonas-schievink

Before this PR, we used to index every crate in the `CrateGraph`, which includes every test, benchmark and example of all packages everywhere. The point of indexing is to speed up future queries, so indexing lots of tiny crates users are unlikely to open isn't really helpful.

This PR instead makes us index only the transitive dependencies of all workspace crates.

This reduces the number of crates we index in the rust-analyzer repo from 617 to 177 (!). Time is not impacted by that much, because most of the skipped crates are tiny.

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-11-11 13:45:20 +00:00 committed by GitHub
commit e42ff91f00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,7 +4,8 @@
//! various caches, it's not really advanced at the moment.
use hir::db::DefDatabase;
use ide_db::base_db::SourceDatabase;
use ide_db::base_db::{CrateGraph, CrateId, SourceDatabase, SourceDatabaseExt};
use rustc_hash::FxHashSet;
use crate::RootDatabase;
@ -19,7 +20,18 @@ pub struct PrimeCachesProgress {
pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress) + Sync)) {
let _p = profile::span("prime_caches");
let graph = db.crate_graph();
let topo = &graph.crates_in_topological_order();
// We're only interested in the transitive dependencies of all workspace crates.
let to_prime: FxHashSet<_> = graph
.iter()
.filter(|&id| {
let file_id = graph[id].root_file_id;
let root_id = db.file_source_root(file_id);
!db.source_root(root_id).is_library
})
.flat_map(|id| graph.transitive_deps(id))
.collect();
let topo = toposort(&graph, &to_prime);
// FIXME: This would be easy to parallelize, since it's in the ideal ordering for that.
// Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks
@ -32,3 +44,16 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress)
db.import_map(crate_id);
}
}
fn toposort(graph: &CrateGraph, crates: &FxHashSet<CrateId>) -> Vec<CrateId> {
// Just subset the full topologically sorted set for simplicity.
let all = graph.crates_in_topological_order();
let mut result = Vec::with_capacity(crates.len());
for krate in all {
if crates.contains(&krate) {
result.push(krate);
}
}
result
}