aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/cli/analysis_bench.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/cli/analysis_bench.rs')
-rw-r--r--crates/ra_lsp_server/src/cli/analysis_bench.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/crates/ra_lsp_server/src/cli/analysis_bench.rs b/crates/ra_lsp_server/src/cli/analysis_bench.rs
new file mode 100644
index 000000000..e00f81073
--- /dev/null
+++ b/crates/ra_lsp_server/src/cli/analysis_bench.rs
@@ -0,0 +1,158 @@
1//! FIXME: write short doc here
2
3use std::{
4 path::{Path, PathBuf},
5 str::FromStr,
6 sync::Arc,
7 time::Instant,
8};
9
10use anyhow::{format_err, Result};
11use ra_db::{
12 salsa::{Database, Durability},
13 FileId, SourceDatabaseExt,
14};
15use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol};
16
17use crate::cli::{load_cargo::load_cargo, Verbosity};
18
19pub enum BenchWhat {
20 Highlight { path: PathBuf },
21 Complete(Position),
22 GotoDef(Position),
23}
24
25pub struct Position {
26 pub path: PathBuf,
27 pub line: u32,
28 pub column: u32,
29}
30
31impl FromStr for Position {
32 type Err = anyhow::Error;
33 fn from_str(s: &str) -> Result<Self> {
34 let (path_line, column) = rsplit_at_char(s, ':')?;
35 let (path, line) = rsplit_at_char(path_line, ':')?;
36 Ok(Position { path: path.into(), line: line.parse()?, column: column.parse()? })
37 }
38}
39
40fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> {
41 let idx = s.rfind(c).ok_or_else(|| format_err!("no `{}` in {}", c, s))?;
42 Ok((&s[..idx], &s[idx + 1..]))
43}
44
45pub fn analysis_bench(verbosity: Verbosity, path: &Path, what: BenchWhat) -> Result<()> {
46 ra_prof::init();
47
48 let start = Instant::now();
49 eprint!("loading: ");
50 let (mut host, roots) = load_cargo(path)?;
51 let db = host.raw_database();
52 eprintln!("{:?}\n", start.elapsed());
53
54 let file_id = {
55 let path = match &what {
56 BenchWhat::Highlight { path } => path,
57 BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => &pos.path,
58 };
59 let path = std::env::current_dir()?.join(path).canonicalize()?;
60 roots
61 .iter()
62 .find_map(|(source_root_id, project_root)| {
63 if project_root.is_member() {
64 for file_id in db.source_root(*source_root_id).walk() {
65 let rel_path = db.file_relative_path(file_id);
66 let abs_path = rel_path.to_path(project_root.path());
67 if abs_path == path {
68 return Some(file_id);
69 }
70 }
71 }
72 None
73 })
74 .ok_or_else(|| format_err!("Can't find {}", path.display()))?
75 };
76
77 match &what {
78 BenchWhat::Highlight { .. } => {
79 let res = do_work(&mut host, file_id, |analysis| {
80 analysis.diagnostics(file_id).unwrap();
81 analysis.highlight_as_html(file_id, false).unwrap()
82 });
83 if verbosity.is_verbose() {
84 println!("\n{}", res);
85 }
86 }
87 BenchWhat::Complete(pos) | BenchWhat::GotoDef(pos) => {
88 let is_completion = match what {
89 BenchWhat::Complete(..) => true,
90 _ => false,
91 };
92
93 let offset = host
94 .analysis()
95 .file_line_index(file_id)?
96 .offset(LineCol { line: pos.line - 1, col_utf16: pos.column });
97 let file_postion = FilePosition { file_id, offset };
98
99 if is_completion {
100 let res =
101 do_work(&mut host, file_id, |analysis| analysis.completions(file_postion));
102 if verbosity.is_verbose() {
103 println!("\n{:#?}", res);
104 }
105 } else {
106 let res =
107 do_work(&mut host, file_id, |analysis| analysis.goto_definition(file_postion));
108 if verbosity.is_verbose() {
109 println!("\n{:#?}", res);
110 }
111 }
112 }
113 }
114 Ok(())
115}
116
117fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, work: F) -> T {
118 {
119 let start = Instant::now();
120 eprint!("from scratch: ");
121 work(&host.analysis());
122 eprintln!("{:?}", start.elapsed());
123 }
124 {
125 let start = Instant::now();
126 eprint!("no change: ");
127 work(&host.analysis());
128 eprintln!("{:?}", start.elapsed());
129 }
130 {
131 let start = Instant::now();
132 eprint!("trivial change: ");
133 host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::LOW);
134 work(&host.analysis());
135 eprintln!("{:?}", start.elapsed());
136 }
137 {
138 let start = Instant::now();
139 eprint!("comment change: ");
140 {
141 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
142 text.push_str("\n/* Hello world */\n");
143 let mut change = AnalysisChange::new();
144 change.change_file(file_id, Arc::new(text));
145 host.apply_change(change);
146 }
147 work(&host.analysis());
148 eprintln!("{:?}", start.elapsed());
149 }
150 {
151 let start = Instant::now();
152 eprint!("const change: ");
153 host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::HIGH);
154 let res = work(&host.analysis());
155 eprintln!("{:?}", start.elapsed());
156 res
157 }
158}