rust/crates/ra_cli/src/analysis_bench.rs
Aleksey Kladov 6314e62cfb add analysis-bench to benchmark incremental analysis
Can be used like this:

```
$ cargo run --release -p ra_cli -- \
  analysis-bench ../chalk/ \
  --complete ../chalk/chalk-engine/src/logic.rs:94:0

loading: 225.970093ms

from scratch:   8.492373325s
no change:      445.265µs
trivial change: 95.631242ms
```

Or like this:

```
$ cargo run --release -p ra_cli -- \
  analysis-bench ../chalk/ \
  --highlight ../chalk/chalk-engine/src/logic.rs

loading: 209.873484ms

from scratch:   9.504916942s
no change:      7.731119ms
trivial change: 124.984039ms
```

"from scratch" includes initial analysis of the relevant bits of the
project

"no change" just asks the same question for the second time. It
measures overhead on assembling the answer outside of salsa.

"trivial change" doesn't do an actual salsa change, it just advances
the revision. This test how fast is salsa at validating things.
2019-06-16 19:45:05 +03:00

93 lines
2.7 KiB
Rust

use std::{
path::{PathBuf, Path},
time::Instant,
};
use ra_db::{SourceDatabase, salsa::Database};
use ra_ide_api::{AnalysisHost, Analysis, LineCol, FilePosition};
use crate::Result;
pub(crate) enum Op {
Highlight { path: PathBuf },
Complete { path: PathBuf, line: u32, column: u32 },
}
pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> {
let start = Instant::now();
eprint!("loading: ");
let (host, roots) = ra_batch::load_cargo(path)?;
let db = host.raw_database();
eprintln!("{:?}\n", start.elapsed());
let file_id = {
let path = match &op {
Op::Highlight { path } => path,
Op::Complete { path, .. } => path,
};
let path = std::env::current_dir()?.join(path).canonicalize()?;
roots
.iter()
.find_map(|(source_root_id, project_root)| {
if project_root.is_member() {
for (rel_path, file_id) in &db.source_root(*source_root_id).files {
let abs_path = rel_path.to_path(project_root.path());
if abs_path == path {
return Some(*file_id);
}
}
}
None
})
.ok_or_else(|| format!("Can't find {:?}", path))?
};
match op {
Op::Highlight { .. } => {
let res = do_work(&host, |analysis| {
analysis.diagnostics(file_id).unwrap();
analysis.highlight_as_html(file_id, false).unwrap()
});
if verbose {
println!("\n{}", res);
}
}
Op::Complete { line, column, .. } => {
let offset = host
.analysis()
.file_line_index(file_id)
.offset(LineCol { line, col_utf16: column });
let file_postion = FilePosition { file_id, offset };
let res = do_work(&host, |analysis| analysis.completions(file_postion));
if verbose {
println!("\n{:#?}", res);
}
}
}
Ok(())
}
fn do_work<F: Fn(&Analysis) -> T, T>(host: &AnalysisHost, work: F) -> T {
{
let start = Instant::now();
eprint!("from scratch: ");
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("no change: ");
work(&host.analysis());
eprintln!("{:?}", start.elapsed());
}
{
let start = Instant::now();
eprint!("trivial change: ");
host.raw_database().salsa_runtime().next_revision();
let res = work(&host.analysis());
eprintln!("{:?}", start.elapsed());
res
}
}