]>
Commit | Line | Data |
---|---|---|
064997fb FG |
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 | //! | |
f2b60f7d FG |
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" | |
064997fb FG |
11 | //! which you can use to paste the command in terminal and add `--release` manually. |
12 | ||
13 | use std::sync::Arc; | |
14 | ||
15 | use ide::{CallableSnippets, Change, CompletionConfig, FilePosition, TextSize}; | |
16 | use ide_db::{ | |
17 | imports::insert_use::{ImportGranularity, InsertUseConfig}, | |
18 | SnippetCap, | |
19 | }; | |
20 | use project_model::CargoConfig; | |
21 | use test_utils::project_root; | |
22 | use vfs::{AbsPathBuf, VfsPath}; | |
23 | ||
24 | use crate::cli::load_cargo::{load_workspace_at, LoadCargoConfig}; | |
25 | ||
26 | #[test] | |
27 | fn integrated_highlighting_benchmark() { | |
28 | if std::env::var("RUN_SLOW_BENCHES").is_err() { | |
29 | return; | |
30 | } | |
31 | ||
32 | // Load rust-analyzer itself. | |
33 | let workspace_to_load = project_root(); | |
34 | let file = "./crates/ide-db/src/apply_change.rs"; | |
35 | ||
36 | let cargo_config = CargoConfig::default(); | |
37 | let load_cargo_config = LoadCargoConfig { | |
38 | load_out_dirs_from_check: true, | |
39 | with_proc_macro: false, | |
40 | prefill_caches: false, | |
41 | }; | |
42 | ||
43 | let (mut host, vfs, _proc_macro) = { | |
44 | let _it = stdx::timeit("workspace loading"); | |
45 | load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap() | |
46 | }; | |
47 | ||
48 | let file_id = { | |
49 | let file = workspace_to_load.join(file); | |
50 | let path = VfsPath::from(AbsPathBuf::assert(file)); | |
9c376795 | 51 | vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) |
064997fb FG |
52 | }; |
53 | ||
54 | { | |
55 | let _it = stdx::timeit("initial"); | |
56 | let analysis = host.analysis(); | |
57 | analysis.highlight_as_html(file_id, false).unwrap(); | |
58 | } | |
59 | ||
60 | profile::init_from("*>100"); | |
61 | // let _s = profile::heartbeat_span(); | |
62 | ||
63 | { | |
64 | let _it = stdx::timeit("change"); | |
65 | let mut text = host.analysis().file_text(file_id).unwrap().to_string(); | |
66 | text.push_str("\npub fn _dummy() {}\n"); | |
67 | let mut change = Change::new(); | |
68 | change.change_file(file_id, Some(Arc::new(text))); | |
69 | host.apply_change(change); | |
70 | } | |
71 | ||
72 | { | |
73 | let _it = stdx::timeit("after change"); | |
74 | let _span = profile::cpu_span(); | |
75 | let analysis = host.analysis(); | |
76 | analysis.highlight_as_html(file_id, false).unwrap(); | |
77 | } | |
78 | } | |
79 | ||
80 | #[test] | |
81 | fn integrated_completion_benchmark() { | |
82 | if std::env::var("RUN_SLOW_BENCHES").is_err() { | |
83 | return; | |
84 | } | |
85 | ||
86 | // Load rust-analyzer itself. | |
87 | let workspace_to_load = project_root(); | |
88 | let file = "./crates/hir/src/lib.rs"; | |
89 | ||
90 | let cargo_config = CargoConfig::default(); | |
91 | let load_cargo_config = LoadCargoConfig { | |
92 | load_out_dirs_from_check: true, | |
93 | with_proc_macro: false, | |
94 | prefill_caches: true, | |
95 | }; | |
96 | ||
97 | let (mut host, vfs, _proc_macro) = { | |
98 | let _it = stdx::timeit("workspace loading"); | |
99 | load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap() | |
100 | }; | |
101 | ||
102 | let file_id = { | |
103 | let file = workspace_to_load.join(file); | |
104 | let path = VfsPath::from(AbsPathBuf::assert(file)); | |
9c376795 | 105 | vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) |
064997fb FG |
106 | }; |
107 | ||
108 | { | |
109 | let _it = stdx::timeit("initial"); | |
110 | let analysis = host.analysis(); | |
111 | analysis.highlight_as_html(file_id, false).unwrap(); | |
112 | } | |
113 | ||
114 | profile::init_from("*>5"); | |
115 | // let _s = profile::heartbeat_span(); | |
116 | ||
117 | let completion_offset = { | |
118 | let _it = stdx::timeit("change"); | |
119 | let mut text = host.analysis().file_text(file_id).unwrap().to_string(); | |
120 | let completion_offset = | |
121 | patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)") | |
122 | + "sel".len(); | |
123 | let mut change = Change::new(); | |
124 | change.change_file(file_id, Some(Arc::new(text))); | |
125 | host.apply_change(change); | |
126 | completion_offset | |
127 | }; | |
128 | ||
129 | { | |
130 | let _p = profile::span("unqualified path completion"); | |
131 | let _span = profile::cpu_span(); | |
132 | let analysis = host.analysis(); | |
133 | let config = CompletionConfig { | |
134 | enable_postfix_completions: true, | |
135 | enable_imports_on_the_fly: true, | |
136 | enable_self_on_the_fly: true, | |
137 | enable_private_editable: true, | |
138 | callable: Some(CallableSnippets::FillArguments), | |
139 | snippet_cap: SnippetCap::new(true), | |
140 | insert_use: InsertUseConfig { | |
141 | granularity: ImportGranularity::Crate, | |
142 | prefix_kind: hir::PrefixKind::ByCrate, | |
143 | enforce_granularity: true, | |
144 | group: true, | |
145 | skip_glob_imports: true, | |
146 | }, | |
147 | snippets: Vec::new(), | |
2b03887a | 148 | prefer_no_std: false, |
064997fb FG |
149 | }; |
150 | let position = | |
151 | FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; | |
152 | analysis.completions(&config, position, None).unwrap(); | |
153 | } | |
154 | ||
155 | let completion_offset = { | |
156 | let _it = stdx::timeit("change"); | |
157 | let mut text = host.analysis().file_text(file_id).unwrap().to_string(); | |
158 | let completion_offset = | |
159 | patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)") | |
160 | + "self.".len(); | |
161 | let mut change = Change::new(); | |
162 | change.change_file(file_id, Some(Arc::new(text))); | |
163 | host.apply_change(change); | |
164 | completion_offset | |
165 | }; | |
166 | ||
167 | { | |
168 | let _p = profile::span("dot completion"); | |
169 | let _span = profile::cpu_span(); | |
170 | let analysis = host.analysis(); | |
171 | let config = CompletionConfig { | |
172 | enable_postfix_completions: true, | |
173 | enable_imports_on_the_fly: true, | |
174 | enable_self_on_the_fly: true, | |
175 | enable_private_editable: true, | |
176 | callable: Some(CallableSnippets::FillArguments), | |
177 | snippet_cap: SnippetCap::new(true), | |
178 | insert_use: InsertUseConfig { | |
179 | granularity: ImportGranularity::Crate, | |
180 | prefix_kind: hir::PrefixKind::ByCrate, | |
181 | enforce_granularity: true, | |
182 | group: true, | |
183 | skip_glob_imports: true, | |
184 | }, | |
185 | snippets: Vec::new(), | |
2b03887a | 186 | prefer_no_std: false, |
064997fb FG |
187 | }; |
188 | let position = | |
189 | FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; | |
190 | analysis.completions(&config, position, None).unwrap(); | |
191 | } | |
192 | } | |
193 | ||
194 | fn patch(what: &mut String, from: &str, to: &str) -> usize { | |
195 | let idx = what.find(from).unwrap(); | |
196 | *what = what.replacen(from, to, 1); | |
197 | idx | |
198 | } |