diff options
Diffstat (limited to 'crates/ra_ide_db/src/change.rs')
-rw-r--r-- | crates/ra_ide_db/src/change.rs | 254 |
1 files changed, 80 insertions, 174 deletions
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 8446ef88e..a1bb3043b 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -5,45 +5,29 @@ use std::{fmt, sync::Arc, time}; | |||
5 | 5 | ||
6 | use ra_db::{ | 6 | use ra_db::{ |
7 | salsa::{Database, Durability, SweepStrategy}, | 7 | salsa::{Database, Durability, SweepStrategy}, |
8 | CrateGraph, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, | 8 | CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, |
9 | SourceRootId, | ||
10 | }; | 9 | }; |
11 | use ra_prof::{memory_usage, profile, Bytes}; | 10 | use ra_prof::{memory_usage, profile, Bytes}; |
12 | use ra_syntax::SourceFile; | 11 | use rustc_hash::FxHashSet; |
13 | #[cfg(not(feature = "wasm"))] | 12 | |
14 | use rayon::prelude::*; | 13 | use crate::{symbol_index::SymbolsDatabase, RootDatabase}; |
15 | use rustc_hash::FxHashMap; | ||
16 | |||
17 | use crate::{ | ||
18 | symbol_index::{SymbolIndex, SymbolsDatabase}, | ||
19 | DebugData, RootDatabase, | ||
20 | }; | ||
21 | 14 | ||
22 | #[derive(Default)] | 15 | #[derive(Default)] |
23 | pub struct AnalysisChange { | 16 | pub struct AnalysisChange { |
24 | new_roots: Vec<(SourceRootId, bool)>, | 17 | roots: Option<Vec<SourceRoot>>, |
25 | roots_changed: FxHashMap<SourceRootId, RootChange>, | 18 | files_changed: Vec<(FileId, Option<Arc<String>>)>, |
26 | files_changed: Vec<(FileId, Arc<String>)>, | ||
27 | libraries_added: Vec<LibraryData>, | ||
28 | crate_graph: Option<CrateGraph>, | 19 | crate_graph: Option<CrateGraph>, |
29 | debug_data: DebugData, | ||
30 | } | 20 | } |
31 | 21 | ||
32 | impl fmt::Debug for AnalysisChange { | 22 | impl fmt::Debug for AnalysisChange { |
33 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 23 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
34 | let mut d = fmt.debug_struct("AnalysisChange"); | 24 | let mut d = fmt.debug_struct("AnalysisChange"); |
35 | if !self.new_roots.is_empty() { | 25 | if let Some(roots) = &self.roots { |
36 | d.field("new_roots", &self.new_roots); | 26 | d.field("roots", roots); |
37 | } | ||
38 | if !self.roots_changed.is_empty() { | ||
39 | d.field("roots_changed", &self.roots_changed); | ||
40 | } | 27 | } |
41 | if !self.files_changed.is_empty() { | 28 | if !self.files_changed.is_empty() { |
42 | d.field("files_changed", &self.files_changed.len()); | 29 | d.field("files_changed", &self.files_changed.len()); |
43 | } | 30 | } |
44 | if !self.libraries_added.is_empty() { | ||
45 | d.field("libraries_added", &self.libraries_added.len()); | ||
46 | } | ||
47 | if self.crate_graph.is_some() { | 31 | if self.crate_graph.is_some() { |
48 | d.field("crate_graph", &self.crate_graph); | 32 | d.field("crate_graph", &self.crate_graph); |
49 | } | 33 | } |
@@ -56,54 +40,30 @@ impl AnalysisChange { | |||
56 | AnalysisChange::default() | 40 | AnalysisChange::default() |
57 | } | 41 | } |
58 | 42 | ||
59 | pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) { | 43 | pub fn set_roots(&mut self, roots: Vec<SourceRoot>) { |
60 | self.new_roots.push((root_id, is_local)); | 44 | self.roots = Some(roots); |
61 | } | 45 | } |
62 | 46 | ||
63 | pub fn add_file( | 47 | pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) { |
64 | &mut self, | ||
65 | root_id: SourceRootId, | ||
66 | file_id: FileId, | ||
67 | path: RelativePathBuf, | ||
68 | text: Arc<String>, | ||
69 | ) { | ||
70 | let file = AddFile { file_id, path, text }; | ||
71 | self.roots_changed.entry(root_id).or_default().added.push(file); | ||
72 | } | ||
73 | |||
74 | pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { | ||
75 | self.files_changed.push((file_id, new_text)) | 48 | self.files_changed.push((file_id, new_text)) |
76 | } | 49 | } |
77 | 50 | ||
78 | pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { | ||
79 | let file = RemoveFile { file_id, path }; | ||
80 | self.roots_changed.entry(root_id).or_default().removed.push(file); | ||
81 | } | ||
82 | |||
83 | pub fn add_library(&mut self, data: LibraryData) { | ||
84 | self.libraries_added.push(data) | ||
85 | } | ||
86 | |||
87 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 51 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
88 | self.crate_graph = Some(graph); | 52 | self.crate_graph = Some(graph); |
89 | } | 53 | } |
90 | |||
91 | pub fn set_debug_root_path(&mut self, source_root_id: SourceRootId, path: String) { | ||
92 | self.debug_data.root_paths.insert(source_root_id, path); | ||
93 | } | ||
94 | } | 54 | } |
95 | 55 | ||
96 | #[derive(Debug)] | 56 | #[derive(Debug)] |
97 | struct AddFile { | 57 | struct AddFile { |
98 | file_id: FileId, | 58 | file_id: FileId, |
99 | path: RelativePathBuf, | 59 | path: String, |
100 | text: Arc<String>, | 60 | text: Arc<String>, |
101 | } | 61 | } |
102 | 62 | ||
103 | #[derive(Debug)] | 63 | #[derive(Debug)] |
104 | struct RemoveFile { | 64 | struct RemoveFile { |
105 | file_id: FileId, | 65 | file_id: FileId, |
106 | path: RelativePathBuf, | 66 | path: String, |
107 | } | 67 | } |
108 | 68 | ||
109 | #[derive(Default)] | 69 | #[derive(Default)] |
@@ -121,47 +81,6 @@ impl fmt::Debug for RootChange { | |||
121 | } | 81 | } |
122 | } | 82 | } |
123 | 83 | ||
124 | pub struct LibraryData { | ||
125 | root_id: SourceRootId, | ||
126 | root_change: RootChange, | ||
127 | symbol_index: SymbolIndex, | ||
128 | } | ||
129 | |||
130 | impl fmt::Debug for LibraryData { | ||
131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
132 | f.debug_struct("LibraryData") | ||
133 | .field("root_id", &self.root_id) | ||
134 | .field("root_change", &self.root_change) | ||
135 | .field("n_symbols", &self.symbol_index.len()) | ||
136 | .finish() | ||
137 | } | ||
138 | } | ||
139 | |||
140 | impl LibraryData { | ||
141 | pub fn prepare( | ||
142 | root_id: SourceRootId, | ||
143 | files: Vec<(FileId, RelativePathBuf, Arc<String>)>, | ||
144 | ) -> LibraryData { | ||
145 | let _p = profile("LibraryData::prepare"); | ||
146 | |||
147 | #[cfg(not(feature = "wasm"))] | ||
148 | let iter = files.par_iter(); | ||
149 | #[cfg(feature = "wasm")] | ||
150 | let iter = files.iter(); | ||
151 | |||
152 | let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| { | ||
153 | let parse = SourceFile::parse(text); | ||
154 | (*file_id, parse) | ||
155 | })); | ||
156 | let mut root_change = RootChange::default(); | ||
157 | root_change.added = files | ||
158 | .into_iter() | ||
159 | .map(|(file_id, path, text)| AddFile { file_id, path, text }) | ||
160 | .collect(); | ||
161 | LibraryData { root_id, root_change, symbol_index } | ||
162 | } | ||
163 | } | ||
164 | |||
165 | const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); | 84 | const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); |
166 | 85 | ||
167 | impl RootDatabase { | 86 | impl RootDatabase { |
@@ -174,72 +93,37 @@ impl RootDatabase { | |||
174 | let _p = profile("RootDatabase::apply_change"); | 93 | let _p = profile("RootDatabase::apply_change"); |
175 | self.request_cancellation(); | 94 | self.request_cancellation(); |
176 | log::info!("apply_change {:?}", change); | 95 | log::info!("apply_change {:?}", change); |
177 | if !change.new_roots.is_empty() { | 96 | if let Some(roots) = change.roots { |
178 | let mut local_roots = Vec::clone(&self.local_roots()); | 97 | let mut local_roots = FxHashSet::default(); |
179 | for (root_id, is_local) in change.new_roots { | 98 | let mut library_roots = FxHashSet::default(); |
180 | let root = | 99 | for (idx, root) in roots.into_iter().enumerate() { |
181 | if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() }; | 100 | let root_id = SourceRootId(idx as u32); |
182 | let durability = durability(&root); | 101 | let durability = durability(&root); |
183 | self.set_source_root_with_durability(root_id, Arc::new(root), durability); | 102 | if root.is_library { |
184 | if is_local { | 103 | library_roots.insert(root_id); |
185 | local_roots.push(root_id); | 104 | } else { |
105 | local_roots.insert(root_id); | ||
186 | } | 106 | } |
107 | for file_id in root.iter() { | ||
108 | self.set_file_source_root_with_durability(file_id, root_id, durability); | ||
109 | } | ||
110 | self.set_source_root_with_durability(root_id, Arc::new(root), durability); | ||
187 | } | 111 | } |
188 | self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); | 112 | self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); |
113 | self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH); | ||
189 | } | 114 | } |
190 | 115 | ||
191 | for (root_id, root_change) in change.roots_changed { | ||
192 | self.apply_root_change(root_id, root_change); | ||
193 | } | ||
194 | for (file_id, text) in change.files_changed { | 116 | for (file_id, text) in change.files_changed { |
195 | let source_root_id = self.file_source_root(file_id); | 117 | let source_root_id = self.file_source_root(file_id); |
196 | let source_root = self.source_root(source_root_id); | 118 | let source_root = self.source_root(source_root_id); |
197 | let durability = durability(&source_root); | 119 | let durability = durability(&source_root); |
120 | // XXX: can't actually remove the file, just reset the text | ||
121 | let text = text.unwrap_or_default(); | ||
198 | self.set_file_text_with_durability(file_id, text, durability) | 122 | self.set_file_text_with_durability(file_id, text, durability) |
199 | } | 123 | } |
200 | if !change.libraries_added.is_empty() { | ||
201 | let mut libraries = Vec::clone(&self.library_roots()); | ||
202 | for library in change.libraries_added { | ||
203 | libraries.push(library.root_id); | ||
204 | self.set_source_root_with_durability( | ||
205 | library.root_id, | ||
206 | Arc::new(SourceRoot::new_library()), | ||
207 | Durability::HIGH, | ||
208 | ); | ||
209 | self.set_library_symbols_with_durability( | ||
210 | library.root_id, | ||
211 | Arc::new(library.symbol_index), | ||
212 | Durability::HIGH, | ||
213 | ); | ||
214 | self.apply_root_change(library.root_id, library.root_change); | ||
215 | } | ||
216 | self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH); | ||
217 | } | ||
218 | if let Some(crate_graph) = change.crate_graph { | 124 | if let Some(crate_graph) = change.crate_graph { |
219 | self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH) | 125 | self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH) |
220 | } | 126 | } |
221 | |||
222 | Arc::make_mut(&mut self.debug_data).merge(change.debug_data) | ||
223 | } | ||
224 | |||
225 | fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) { | ||
226 | let mut source_root = SourceRoot::clone(&self.source_root(root_id)); | ||
227 | let durability = durability(&source_root); | ||
228 | for add_file in root_change.added { | ||
229 | self.set_file_text_with_durability(add_file.file_id, add_file.text, durability); | ||
230 | self.set_file_relative_path_with_durability( | ||
231 | add_file.file_id, | ||
232 | add_file.path.clone(), | ||
233 | durability, | ||
234 | ); | ||
235 | self.set_file_source_root_with_durability(add_file.file_id, root_id, durability); | ||
236 | source_root.insert_file(add_file.path, add_file.file_id); | ||
237 | } | ||
238 | for remove_file in root_change.removed { | ||
239 | self.set_file_text_with_durability(remove_file.file_id, Default::default(), durability); | ||
240 | source_root.remove_file(&remove_file.path); | ||
241 | } | ||
242 | self.set_source_root_with_durability(root_id, Arc::new(source_root), durability); | ||
243 | } | 127 | } |
244 | 128 | ||
245 | pub fn maybe_collect_garbage(&mut self) { | 129 | pub fn maybe_collect_garbage(&mut self) { |
@@ -262,37 +146,46 @@ impl RootDatabase { | |||
262 | 146 | ||
263 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); | 147 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); |
264 | 148 | ||
265 | self.query(ra_db::ParseQuery).sweep(sweep); | 149 | ra_db::ParseQuery.in_db(self).sweep(sweep); |
266 | self.query(hir::db::ParseMacroQuery).sweep(sweep); | 150 | hir::db::ParseMacroQuery.in_db(self).sweep(sweep); |
267 | 151 | ||
268 | // Macros do take significant space, but less then the syntax trees | 152 | // Macros do take significant space, but less then the syntax trees |
269 | // self.query(hir::db::MacroDefQuery).sweep(sweep); | 153 | // self.query(hir::db::MacroDefQuery).sweep(sweep); |
270 | // self.query(hir::db::MacroArgQuery).sweep(sweep); | 154 | // self.query(hir::db::MacroArgQuery).sweep(sweep); |
271 | // self.query(hir::db::MacroExpandQuery).sweep(sweep); | 155 | // self.query(hir::db::MacroExpandQuery).sweep(sweep); |
272 | 156 | ||
273 | self.query(hir::db::AstIdMapQuery).sweep(sweep); | 157 | hir::db::AstIdMapQuery.in_db(self).sweep(sweep); |
274 | 158 | ||
275 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); | 159 | hir::db::BodyWithSourceMapQuery.in_db(self).sweep(sweep); |
276 | 160 | ||
277 | self.query(hir::db::ExprScopesQuery).sweep(sweep); | 161 | hir::db::ExprScopesQuery.in_db(self).sweep(sweep); |
278 | self.query(hir::db::InferQueryQuery).sweep(sweep); | 162 | hir::db::InferQueryQuery.in_db(self).sweep(sweep); |
279 | self.query(hir::db::BodyQuery).sweep(sweep); | 163 | hir::db::BodyQuery.in_db(self).sweep(sweep); |
280 | } | 164 | } |
281 | 165 | ||
166 | // Feature: Memory Usage | ||
167 | // | ||
168 | // Clears rust-analyzer's internal database and prints memory usage statistics. | ||
169 | // | ||
170 | // |=== | ||
171 | // | Editor | Action Name | ||
172 | // | ||
173 | // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)** | ||
174 | // |=== | ||
282 | pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { | 175 | pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { |
283 | let mut acc: Vec<(String, Bytes)> = vec![]; | 176 | let mut acc: Vec<(String, Bytes)> = vec![]; |
284 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); | 177 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); |
285 | macro_rules! sweep_each_query { | 178 | macro_rules! sweep_each_query { |
286 | ($($q:path)*) => {$( | 179 | ($($q:path)*) => {$( |
287 | let before = memory_usage().allocated; | 180 | let before = memory_usage().allocated; |
288 | self.query($q).sweep(sweep); | 181 | $q.in_db(self).sweep(sweep); |
289 | let after = memory_usage().allocated; | 182 | let after = memory_usage().allocated; |
290 | let q: $q = Default::default(); | 183 | let q: $q = Default::default(); |
291 | let name = format!("{:?}", q); | 184 | let name = format!("{:?}", q); |
292 | acc.push((name, before - after)); | 185 | acc.push((name, before - after)); |
293 | 186 | ||
294 | let before = memory_usage().allocated; | 187 | let before = memory_usage().allocated; |
295 | self.query($q).sweep(sweep.discard_everything()); | 188 | $q.in_db(self).sweep(sweep.discard_everything()); |
296 | let after = memory_usage().allocated; | 189 | let after = memory_usage().allocated; |
297 | let q: $q = Default::default(); | 190 | let q: $q = Default::default(); |
298 | let name = format!("{:?} (deps)", q); | 191 | let name = format!("{:?} (deps)", q); |
@@ -306,15 +199,13 @@ impl RootDatabase { | |||
306 | 199 | ||
307 | // AstDatabase | 200 | // AstDatabase |
308 | hir::db::AstIdMapQuery | 201 | hir::db::AstIdMapQuery |
309 | hir::db::InternMacroQuery | ||
310 | hir::db::MacroArgQuery | 202 | hir::db::MacroArgQuery |
311 | hir::db::MacroDefQuery | 203 | hir::db::MacroDefQuery |
312 | hir::db::ParseMacroQuery | 204 | hir::db::ParseMacroQuery |
313 | hir::db::MacroExpandQuery | 205 | hir::db::MacroExpandQuery |
314 | hir::db::InternEagerExpansionQuery | ||
315 | 206 | ||
316 | // DefDatabase | 207 | // DefDatabase |
317 | hir::db::RawItemsQuery | 208 | hir::db::ItemTreeQuery |
318 | hir::db::CrateDefMapQueryQuery | 209 | hir::db::CrateDefMapQueryQuery |
319 | hir::db::StructDataQuery | 210 | hir::db::StructDataQuery |
320 | hir::db::UnionDataQuery | 211 | hir::db::UnionDataQuery |
@@ -334,17 +225,7 @@ impl RootDatabase { | |||
334 | hir::db::CrateLangItemsQuery | 225 | hir::db::CrateLangItemsQuery |
335 | hir::db::LangItemQuery | 226 | hir::db::LangItemQuery |
336 | hir::db::DocumentationQuery | 227 | hir::db::DocumentationQuery |
337 | 228 | hir::db::ImportMapQuery | |
338 | // InternDatabase | ||
339 | hir::db::InternFunctionQuery | ||
340 | hir::db::InternStructQuery | ||
341 | hir::db::InternUnionQuery | ||
342 | hir::db::InternEnumQuery | ||
343 | hir::db::InternConstQuery | ||
344 | hir::db::InternStaticQuery | ||
345 | hir::db::InternTraitQuery | ||
346 | hir::db::InternTypeAliasQuery | ||
347 | hir::db::InternImplQuery | ||
348 | 229 | ||
349 | // HirDatabase | 230 | // HirDatabase |
350 | hir::db::InferQueryQuery | 231 | hir::db::InferQueryQuery |
@@ -357,18 +238,16 @@ impl RootDatabase { | |||
357 | hir::db::GenericPredicatesForParamQuery | 238 | hir::db::GenericPredicatesForParamQuery |
358 | hir::db::GenericPredicatesQuery | 239 | hir::db::GenericPredicatesQuery |
359 | hir::db::GenericDefaultsQuery | 240 | hir::db::GenericDefaultsQuery |
360 | hir::db::ImplsInCrateQuery | 241 | hir::db::InherentImplsInCrateQuery |
361 | hir::db::ImplsForTraitQuery | 242 | hir::db::TraitImplsInCrateQuery |
362 | hir::db::InternTypeCtorQuery | 243 | hir::db::TraitImplsInDepsQuery |
363 | hir::db::InternTypeParamIdQuery | ||
364 | hir::db::InternChalkImplQuery | ||
365 | hir::db::InternAssocTyValueQuery | ||
366 | hir::db::AssociatedTyDataQuery | 244 | hir::db::AssociatedTyDataQuery |
367 | hir::db::TraitDatumQuery | 245 | hir::db::TraitDatumQuery |
368 | hir::db::StructDatumQuery | 246 | hir::db::StructDatumQuery |
369 | hir::db::ImplDatumQuery | 247 | hir::db::ImplDatumQuery |
370 | hir::db::AssociatedTyValueQuery | 248 | hir::db::AssociatedTyValueQuery |
371 | hir::db::TraitSolveQuery | 249 | hir::db::TraitSolveQuery |
250 | hir::db::ReturnTypeImplTraitsQuery | ||
372 | 251 | ||
373 | // SymbolsDatabase | 252 | // SymbolsDatabase |
374 | crate::symbol_index::FileSymbolsQuery | 253 | crate::symbol_index::FileSymbolsQuery |
@@ -376,6 +255,33 @@ impl RootDatabase { | |||
376 | // LineIndexDatabase | 255 | // LineIndexDatabase |
377 | crate::LineIndexQuery | 256 | crate::LineIndexQuery |
378 | ]; | 257 | ]; |
258 | |||
259 | // To collect interned data, we need to bump the revision counter by performing a synthetic | ||
260 | // write. | ||
261 | // We do this after collecting the non-interned queries to correctly attribute memory used | ||
262 | // by interned data. | ||
263 | self.salsa_runtime_mut().synthetic_write(Durability::HIGH); | ||
264 | |||
265 | sweep_each_query![ | ||
266 | // AstDatabase | ||
267 | hir::db::InternMacroQuery | ||
268 | hir::db::InternEagerExpansionQuery | ||
269 | |||
270 | // InternDatabase | ||
271 | hir::db::InternFunctionQuery | ||
272 | hir::db::InternStructQuery | ||
273 | hir::db::InternUnionQuery | ||
274 | hir::db::InternEnumQuery | ||
275 | hir::db::InternConstQuery | ||
276 | hir::db::InternStaticQuery | ||
277 | hir::db::InternTraitQuery | ||
278 | hir::db::InternTypeAliasQuery | ||
279 | hir::db::InternImplQuery | ||
280 | |||
281 | // HirDatabase | ||
282 | hir::db::InternTypeParamIdQuery | ||
283 | ]; | ||
284 | |||
379 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 285 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
380 | acc | 286 | acc |
381 | } | 287 | } |