aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/benchmarks.rs74
-rw-r--r--crates/rust-analyzer/src/integrated_benchmarks.rs186
-rw-r--r--crates/rust-analyzer/src/lib.rs2
3 files changed, 187 insertions, 75 deletions
diff --git a/crates/rust-analyzer/src/benchmarks.rs b/crates/rust-analyzer/src/benchmarks.rs
deleted file mode 100644
index bdd94b1c4..000000000
--- a/crates/rust-analyzer/src/benchmarks.rs
+++ /dev/null
@@ -1,74 +0,0 @@
1//! Fully integrated benchmarks for rust-analyzer, which load real cargo
2//! projects.
3//!
4//! The benchmark here is used to debug specific performance regressions. If you
5//! notice that, eg, completion is slow in some specific case, you can modify
6//! code here exercise this specific completion, and thus have a fast
7//! edit/compile/test cycle.
8//!
9//! Note that "Rust Analyzer: Run" action does not allow running a single test
10//! in release mode in VS Code. There's however "Rust Analyzer: Copy Run Command Line"
11//! which you can use to paste the command in terminal and add `--release` manually.
12
13use std::sync::Arc;
14
15use ide::Change;
16use test_utils::project_root;
17use vfs::{AbsPathBuf, VfsPath};
18
19use crate::cli::load_cargo::{load_workspace_at, LoadCargoConfig};
20
21#[test]
22fn benchmark_integrated_highlighting() {
23 // Don't run slow benchmark by default
24 if true {
25 return;
26 }
27
28 // Load rust-analyzer itself.
29 let workspace_to_load = project_root();
30 let file = "./crates/ide_db/src/apply_change.rs";
31
32 let cargo_config = Default::default();
33 let load_cargo_config = LoadCargoConfig {
34 load_out_dirs_from_check: true,
35 wrap_rustc: false,
36 with_proc_macro: false,
37 };
38
39 let (mut host, vfs, _proc_macro) = {
40 let _it = stdx::timeit("workspace loading");
41 load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap()
42 };
43
44 let file_id = {
45 let file = workspace_to_load.join(file);
46 let path = VfsPath::from(AbsPathBuf::assert(file));
47 vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {}", path))
48 };
49
50 {
51 let _it = stdx::timeit("initial");
52 let analysis = host.analysis();
53 analysis.highlight_as_html(file_id, false).unwrap();
54 }
55
56 profile::init_from("*>100");
57 // let _s = profile::heartbeat_span();
58
59 {
60 let _it = stdx::timeit("change");
61 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
62 text.push_str("\npub fn _dummy() {}\n");
63 let mut change = Change::new();
64 change.change_file(file_id, Some(Arc::new(text)));
65 host.apply_change(change);
66 }
67
68 {
69 let _it = stdx::timeit("after change");
70 let _span = profile::cpu_span();
71 let analysis = host.analysis();
72 analysis.highlight_as_html(file_id, false).unwrap();
73 }
74}
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
new file mode 100644
index 000000000..411446b04
--- /dev/null
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -0,0 +1,186 @@
1//! Fully integrated benchmarks for rust-analyzer, which load real cargo
2//! projects.
3//!
4//! The benchmark here is used to debug specific performance regressions. If you
5//! notice that, eg, completion is slow in some specific case, you can modify
6//! code here exercise this specific completion, and thus have a fast
7//! edit/compile/test cycle.
8//!
9//! Note that "Rust Analyzer: Run" action does not allow running a single test
10//! in release mode in VS Code. There's however "Rust Analyzer: Copy Run Command Line"
11//! which you can use to paste the command in terminal and add `--release` manually.
12
13use std::{convert::TryFrom, sync::Arc};
14
15use ide::{Change, CompletionConfig, FilePosition, TextSize};
16use ide_db::helpers::{insert_use::InsertUseConfig, merge_imports::MergeBehavior, SnippetCap};
17use test_utils::project_root;
18use vfs::{AbsPathBuf, VfsPath};
19
20use crate::cli::load_cargo::{load_workspace_at, LoadCargoConfig};
21
22#[test]
23fn integrated_highlighting_benchmark() {
24 // Don't run slow benchmark by default
25 if true {
26 return;
27 }
28
29 // Load rust-analyzer itself.
30 let workspace_to_load = project_root();
31 let file = "./crates/ide_db/src/apply_change.rs";
32
33 let cargo_config = Default::default();
34 let load_cargo_config = LoadCargoConfig {
35 load_out_dirs_from_check: true,
36 wrap_rustc: false,
37 with_proc_macro: false,
38 };
39
40 let (mut host, vfs, _proc_macro) = {
41 let _it = stdx::timeit("workspace loading");
42 load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap()
43 };
44
45 let file_id = {
46 let file = workspace_to_load.join(file);
47 let path = VfsPath::from(AbsPathBuf::assert(file));
48 vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {}", path))
49 };
50
51 {
52 let _it = stdx::timeit("initial");
53 let analysis = host.analysis();
54 analysis.highlight_as_html(file_id, false).unwrap();
55 }
56
57 profile::init_from("*>100");
58 // let _s = profile::heartbeat_span();
59
60 {
61 let _it = stdx::timeit("change");
62 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
63 text.push_str("\npub fn _dummy() {}\n");
64 let mut change = Change::new();
65 change.change_file(file_id, Some(Arc::new(text)));
66 host.apply_change(change);
67 }
68
69 {
70 let _it = stdx::timeit("after change");
71 let _span = profile::cpu_span();
72 let analysis = host.analysis();
73 analysis.highlight_as_html(file_id, false).unwrap();
74 }
75}
76
77#[test]
78fn integrated_completion_benchmark() {
79 // Don't run slow benchmark by default
80 if true {
81 return;
82 }
83
84 // Load rust-analyzer itself.
85 let workspace_to_load = project_root();
86 let file = "./crates/hir/src/lib.rs";
87
88 let cargo_config = Default::default();
89 let load_cargo_config = LoadCargoConfig {
90 load_out_dirs_from_check: true,
91 wrap_rustc: false,
92 with_proc_macro: false,
93 };
94
95 let (mut host, vfs, _proc_macro) = {
96 let _it = stdx::timeit("workspace loading");
97 load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap()
98 };
99
100 let file_id = {
101 let file = workspace_to_load.join(file);
102 let path = VfsPath::from(AbsPathBuf::assert(file));
103 vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {}", path))
104 };
105
106 {
107 let _it = stdx::timeit("initial");
108 let analysis = host.analysis();
109 analysis.highlight_as_html(file_id, false).unwrap();
110 }
111
112 profile::init_from("*>5");
113 // let _s = profile::heartbeat_span();
114
115 let completion_offset = {
116 let _it = stdx::timeit("change");
117 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
118 let completion_offset =
119 patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)")
120 + "sel".len();
121 let mut change = Change::new();
122 change.change_file(file_id, Some(Arc::new(text)));
123 host.apply_change(change);
124 completion_offset
125 };
126
127 {
128 let _it = stdx::timeit("unqualified path completion");
129 let _span = profile::cpu_span();
130 let analysis = host.analysis();
131 let config = CompletionConfig {
132 enable_postfix_completions: true,
133 enable_imports_on_the_fly: true,
134 add_call_parenthesis: true,
135 add_call_argument_snippets: true,
136 snippet_cap: SnippetCap::new(true),
137 insert_use: InsertUseConfig {
138 merge: Some(MergeBehavior::Full),
139 prefix_kind: hir::PrefixKind::ByCrate,
140 group: true,
141 },
142 };
143 let position =
144 FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
145 analysis.completions(&config, position).unwrap();
146 }
147
148 let completion_offset = {
149 let _it = stdx::timeit("change");
150 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
151 let completion_offset =
152 patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)")
153 + "self.".len();
154 let mut change = Change::new();
155 change.change_file(file_id, Some(Arc::new(text)));
156 host.apply_change(change);
157 completion_offset
158 };
159
160 {
161 let _it = stdx::timeit("dot completion");
162 let _span = profile::cpu_span();
163 let analysis = host.analysis();
164 let config = CompletionConfig {
165 enable_postfix_completions: true,
166 enable_imports_on_the_fly: true,
167 add_call_parenthesis: true,
168 add_call_argument_snippets: true,
169 snippet_cap: SnippetCap::new(true),
170 insert_use: InsertUseConfig {
171 merge: Some(MergeBehavior::Full),
172 prefix_kind: hir::PrefixKind::ByCrate,
173 group: true,
174 },
175 };
176 let position =
177 FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
178 analysis.completions(&config, position).unwrap();
179 }
180}
181
182fn patch(what: &mut String, from: &str, to: &str) -> usize {
183 let idx = what.find(from).unwrap();
184 *what = what.replacen(from, to, 1);
185 idx
186}
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index d9a5030a0..da7e24bec 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -40,7 +40,7 @@ pub mod lsp_ext;
40pub mod config; 40pub mod config;
41 41
42#[cfg(test)] 42#[cfg(test)]
43mod benchmarks; 43mod integrated_benchmarks;
44 44
45use serde::de::DeserializeOwned; 45use serde::de::DeserializeOwned;
46use std::fmt; 46use std::fmt;