Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/bin/main.rs1
-rw-r--r--crates/rust-analyzer/src/cli.rs1
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs8
-rw-r--r--crates/rust-analyzer/src/cli/flags.rs26
-rw-r--r--crates/rust-analyzer/src/cli/prime_caches.rs67
-rw-r--r--crates/rust-analyzer/src/cli/progress_report.rs4
6 files changed, 101 insertions, 6 deletions
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 157fe6705d..ea5a5eaa6a 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -88,6 +88,7 @@ fn actual_main() -> anyhow::Result<ExitCode> {
flags::RustAnalyzerCmd::Scip(cmd) => cmd.run()?,
flags::RustAnalyzerCmd::RunTests(cmd) => cmd.run()?,
flags::RustAnalyzerCmd::RustcTests(cmd) => cmd.run()?,
+ flags::RustAnalyzerCmd::PrimeCaches(cmd) => cmd.run()?,
}
Ok(ExitCode::SUCCESS)
}
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs
index 43101be638..6643037220 100644
--- a/crates/rust-analyzer/src/cli.rs
+++ b/crates/rust-analyzer/src/cli.rs
@@ -8,6 +8,7 @@ pub mod flags;
mod highlight;
mod lsif;
mod parse;
+mod prime_caches;
mod run_tests;
mod rustc_tests;
mod scip;
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 1cb4875794..ea832cab44 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -437,7 +437,7 @@ impl flags::AnalysisStats {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.parallel || self.output.is_some() => ProgressReport::hidden(),
- _ => ProgressReport::new(file_ids.len() as u64),
+ _ => ProgressReport::new(file_ids.len()),
};
file_ids.sort();
@@ -646,7 +646,7 @@ impl flags::AnalysisStats {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.parallel || self.output.is_some() => ProgressReport::hidden(),
- _ => ProgressReport::new(bodies.len() as u64),
+ _ => ProgressReport::new(bodies.len()),
};
let mut sw = self.stop_watch();
let mut all = 0;
@@ -692,7 +692,7 @@ impl flags::AnalysisStats {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.parallel || self.output.is_some() => ProgressReport::hidden(),
- _ => ProgressReport::new(bodies.len() as u64),
+ _ => ProgressReport::new(bodies.len()),
};
if self.parallel {
@@ -1023,7 +1023,7 @@ impl flags::AnalysisStats {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.output.is_some() => ProgressReport::hidden(),
- _ => ProgressReport::new(bodies.len() as u64),
+ _ => ProgressReport::new(bodies.len()),
};
let mut sw = self.stop_watch();
diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs
index 13075d4994..3675bd7169 100644
--- a/crates/rust-analyzer/src/cli/flags.rs
+++ b/crates/rust-analyzer/src/cli/flags.rs
@@ -139,6 +139,21 @@ xflags::xflags! {
optional --proc-macro-srv path: PathBuf
}
+ /// prime caches, as rust-analyzer does typically at startup in interactive sessions.
+ cmd prime-caches {
+ /// Directory with Cargo.toml.
+ required path: PathBuf
+
+ /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
+ optional --disable-build-scripts
+ /// Don't use expand proc macros.
+ optional --disable-proc-macros
+ /// Run the proc-macro-srv binary at the specified path.
+ optional --proc-macro-srv path: PathBuf
+ /// Run cache priming in parallel.
+ optional --parallel
+ }
+
cmd ssr {
/// A structured search replace rule (`$a.foo($b) ==>> bar($a, $b)`)
repeated rule: SsrRule
@@ -197,6 +212,7 @@ pub enum RustAnalyzerCmd {
RustcTests(RustcTests),
Diagnostics(Diagnostics),
UnresolvedReferences(UnresolvedReferences),
+ PrimeCaches(PrimeCaches),
Ssr(Ssr),
Search(Search),
Lsif(Lsif),
@@ -277,6 +293,16 @@ pub struct UnresolvedReferences {
}
#[derive(Debug)]
+pub struct PrimeCaches {
+ pub path: PathBuf,
+
+ pub disable_build_scripts: bool,
+ pub disable_proc_macros: bool,
+ pub proc_macro_srv: Option<PathBuf>,
+ pub parallel: bool,
+}
+
+#[derive(Debug)]
pub struct Ssr {
pub rule: Vec<SsrRule>,
}
diff --git a/crates/rust-analyzer/src/cli/prime_caches.rs b/crates/rust-analyzer/src/cli/prime_caches.rs
new file mode 100644
index 0000000000..46fb701ab4
--- /dev/null
+++ b/crates/rust-analyzer/src/cli/prime_caches.rs
@@ -0,0 +1,67 @@
+//! Load the project and run cache priming.
+//!
+//! Unlike `analysis-stats`, this command is intended to be used for
+//! benchmarking rust-analyzer's default startup configuration. It *does not*
+//! attempt to simulate the full IDE experience through the lifetime of the
+//! an editing session.
+
+use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
+use profile::StopWatch;
+use project_model::{ProjectManifest, ProjectWorkspace};
+use vfs::AbsPathBuf;
+
+use crate::cli::flags;
+
+impl flags::PrimeCaches {
+ pub fn run(self) -> anyhow::Result<()> {
+ let root =
+ vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize();
+ let config = crate::config::Config::new(
+ root.clone(),
+ lsp_types::ClientCapabilities::default(),
+ vec![],
+ None,
+ );
+ let mut stop_watch = StopWatch::start();
+
+ let cargo_config = config.cargo(None);
+ let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv {
+ let path = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(p));
+ ProcMacroServerChoice::Explicit(path)
+ } else {
+ ProcMacroServerChoice::Sysroot
+ };
+ let load_cargo_config = LoadCargoConfig {
+ load_out_dirs_from_check: !self.disable_build_scripts,
+ with_proc_macro_server,
+ // while this command is nominally focused on cache priming,
+ // we want to ensure that this command, not `load_workspace_at`,
+ // is responsible for that work.
+ prefill_caches: false,
+ };
+
+ let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root));
+ let root = ProjectManifest::discover_single(&root)?;
+ let workspace = ProjectWorkspace::load(root, &cargo_config, &|_| {})?;
+
+ let (db, _, _) = load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;
+ let elapsed = stop_watch.elapsed();
+ eprintln!(
+ "Load time: {:?}ms, memory allocated: {}MB",
+ elapsed.time.as_millis(),
+ elapsed.memory.allocated.megabytes() as u64
+ );
+
+ let threads = if self.parallel { num_cpus::get() } else { 1 };
+ ide_db::prime_caches::parallel_prime_caches(&db, threads, &|_| ());
+
+ let elapsed = stop_watch.elapsed();
+ eprintln!(
+ "Cache priming time: {:?}ms, total memory allocated: {}MB",
+ elapsed.time.as_millis(),
+ elapsed.memory.allocated.megabytes() as u64
+ );
+
+ Ok(())
+ }
+}
diff --git a/crates/rust-analyzer/src/cli/progress_report.rs b/crates/rust-analyzer/src/cli/progress_report.rs
index c1b1d3f348..1b9b870a7c 100644
--- a/crates/rust-analyzer/src/cli/progress_report.rs
+++ b/crates/rust-analyzer/src/cli/progress_report.rs
@@ -9,13 +9,13 @@ pub(crate) struct ProgressReport<'a> {
text: String,
hidden: bool,
- len: u64,
+ len: usize,
pos: u64,
msg: Option<Box<dyn Fn() -> String + 'a>>,
}
impl<'a> ProgressReport<'a> {
- pub(crate) fn new(len: u64) -> ProgressReport<'a> {
+ pub(crate) fn new(len: usize) -> ProgressReport<'a> {
ProgressReport { curr: 0.0, text: String::new(), hidden: false, len, pos: 0, msg: None }
}