10978: internal: Only prime direct dependencies of the workspace crates r=jonas-schievink a=lnicola

This reduces the number of primed crates on `self` from 177 to 105.

```text
# baseline
  86521 me   20   0 2939M  562M 14320 S  0.0  0.9  0:07.10   37 rust-analyzer

# pr
  99947 me   20   0 2935M  549M 14424 S  0.0  0.9  0:07.10   37 rust-analyzer
```

The RAM usage seems to vary a lot, so I'm not sure the improvement shown above is real.

We also drop the topological sorting, although it might still make sense to do the dependencies before the workspace crates. But since it's only used to make the progress reporting a bit more fine, it probably doesn't matter too much.

Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
This commit is contained in:
bors[bot] 2021-12-10 22:31:55 +00:00 committed by GitHub
commit d03397fe11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -4,7 +4,7 @@
//! various caches, it's not really advanced at the moment.
use hir::db::DefDatabase;
use ide_db::base_db::{CrateGraph, CrateId, SourceDatabase, SourceDatabaseExt};
use ide_db::base_db::{SourceDatabase, SourceDatabaseExt};
use rustc_hash::FxHashSet;
use crate::RootDatabase;
@ -20,7 +20,10 @@ 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();
// We're only interested in the transitive dependencies of all workspace crates.
// We're only interested in the workspace crates and the `ImportMap`s of their direct
// dependencies, though in practice the latter also compute the `DefMap`s.
// We don't prime transitive dependencies because they're generally not visible in
// the current workspace.
let to_prime: FxHashSet<_> = graph
.iter()
.filter(|&id| {
@ -28,32 +31,18 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress)
let root_id = db.file_source_root(file_id);
!db.source_root(root_id).is_library
})
.flat_map(|id| graph.transitive_deps(id))
.flat_map(|id| graph[id].dependencies.iter().map(|krate| krate.crate_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
// cancellation, so we cannot use rayon.
for (i, &crate_id) in topo.iter().enumerate() {
let n_total = to_prime.len();
for (n_done, &crate_id) in to_prime.iter().enumerate() {
let crate_name = graph[crate_id].display_name.as_deref().unwrap_or_default().to_string();
cb(PrimeCachesProgress { on_crate: crate_name, n_done: i, n_total: topo.len() });
db.crate_def_map(crate_id);
cb(PrimeCachesProgress { on_crate: crate_name, n_done, n_total });
// This also computes the DefMap
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
}