1 //! Applies changes to the IDE state transactionally.
3 use std::{fmt, sync::Arc};
6 salsa::{Database, Durability, SweepStrategy},
7 Change, FileId, SourceRootId,
9 use profile::{memory_usage, Bytes};
10 use rustc_hash::FxHashSet;
12 use crate::{symbol_index::SymbolsDatabase, RootDatabase};
30 removed: Vec<RemoveFile>,
33 impl fmt::Debug for RootChange {
34 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
35 fmt.debug_struct("AnalysisChange")
36 .field("added", &self.added.len())
37 .field("removed", &self.removed.len())
43 pub fn request_cancellation(&mut self) {
44 let _p = profile::span("RootDatabase::request_cancellation");
45 self.salsa_runtime_mut().synthetic_write(Durability::LOW);
48 pub fn apply_change(&mut self, change: Change) {
49 let _p = profile::span("RootDatabase::apply_change");
50 self.request_cancellation();
51 log::info!("apply_change {:?}", change);
52 if let Some(roots) = &change.roots {
53 let mut local_roots = FxHashSet::default();
54 let mut library_roots = FxHashSet::default();
55 for (idx, root) in roots.iter().enumerate() {
56 let root_id = SourceRootId(idx as u32);
58 library_roots.insert(root_id);
60 local_roots.insert(root_id);
63 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
64 self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
69 pub fn collect_garbage(&mut self) {
70 if cfg!(feature = "wasm") {
74 let _p = profile::span("RootDatabase::collect_garbage");
76 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
78 base_db::ParseQuery.in_db(self).sweep(sweep);
79 hir::db::ParseMacroExpansionQuery.in_db(self).sweep(sweep);
81 // Macros do take significant space, but less then the syntax trees
82 // self.query(hir::db::MacroDefQuery).sweep(sweep);
83 // self.query(hir::db::MacroArgTextQuery).sweep(sweep);
84 // self.query(hir::db::MacroExpandQuery).sweep(sweep);
86 hir::db::AstIdMapQuery.in_db(self).sweep(sweep);
88 hir::db::BodyWithSourceMapQuery.in_db(self).sweep(sweep);
90 hir::db::ExprScopesQuery.in_db(self).sweep(sweep);
91 hir::db::InferQueryQuery.in_db(self).sweep(sweep);
92 hir::db::BodyQuery.in_db(self).sweep(sweep);
95 // Feature: Memory Usage
97 // Clears rust-analyzer's internal database and prints memory usage statistics.
100 // | Editor | Action Name
102 // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)**
104 pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
105 let mut acc: Vec<(String, Bytes)> = vec![];
106 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
107 macro_rules! sweep_each_query {
109 let before = memory_usage().allocated;
110 $q.in_db(self).sweep(sweep);
111 let after = memory_usage().allocated;
112 let q: $q = Default::default();
113 let name = format!("{:?}", q);
114 acc.push((name, before - after));
116 let before = memory_usage().allocated;
117 $q.in_db(self).sweep(sweep.discard_everything());
118 let after = memory_usage().allocated;
119 let q: $q = Default::default();
120 let name = format!("{:?} (deps)", q);
121 acc.push((name, before - after));
123 let before = memory_usage().allocated;
124 $q.in_db(self).purge();
125 let after = memory_usage().allocated;
126 let q: $q = Default::default();
127 let name = format!("{:?} (purge)", q);
128 acc.push((name, before - after));
134 base_db::CrateGraphQuery
137 base_db::FileTextQuery
138 base_db::FileSourceRootQuery
139 base_db::SourceRootQuery
140 base_db::SourceRootCratesQuery
143 hir::db::AstIdMapQuery
144 hir::db::MacroArgTextQuery
145 hir::db::MacroDefQuery
146 hir::db::ParseMacroExpansionQuery
147 hir::db::MacroExpandQuery
148 hir::db::HygieneFrameQuery
151 hir::db::ItemTreeQuery
152 hir::db::BlockDefMapQuery
153 hir::db::CrateDefMapQueryQuery
154 hir::db::StructDataQuery
155 hir::db::UnionDataQuery
156 hir::db::EnumDataQuery
157 hir::db::ImplDataQuery
158 hir::db::TraitDataQuery
159 hir::db::TypeAliasDataQuery
160 hir::db::FunctionDataQuery
161 hir::db::ConstDataQuery
162 hir::db::StaticDataQuery
163 hir::db::BodyWithSourceMapQuery
165 hir::db::ExprScopesQuery
166 hir::db::GenericParamsQuery
168 hir::db::CrateLangItemsQuery
169 hir::db::LangItemQuery
170 hir::db::ImportMapQuery
173 hir::db::InferQueryQuery
175 hir::db::ValueTyQuery
176 hir::db::ImplSelfTyQuery
177 hir::db::ImplTraitQuery
178 hir::db::FieldTypesQuery
179 hir::db::CallableItemSignatureQuery
180 hir::db::GenericPredicatesForParamQuery
181 hir::db::GenericPredicatesQuery
182 hir::db::GenericDefaultsQuery
183 hir::db::InherentImplsInCrateQuery
184 hir::db::TraitImplsInCrateQuery
185 hir::db::TraitImplsInDepsQuery
186 hir::db::AssociatedTyDataQuery
187 hir::db::AssociatedTyDataQuery
188 hir::db::TraitDatumQuery
189 hir::db::StructDatumQuery
190 hir::db::ImplDatumQuery
191 hir::db::FnDefDatumQuery
192 hir::db::ReturnTypeImplTraitsQuery
193 hir::db::InternCallableDefQuery
194 hir::db::InternTypeParamIdQuery
195 hir::db::InternImplTraitIdQuery
196 hir::db::InternClosureQuery
197 hir::db::AssociatedTyValueQuery
198 hir::db::TraitSolveQuery
201 crate::symbol_index::FileSymbolsQuery
202 crate::symbol_index::LibrarySymbolsQuery
203 crate::symbol_index::LocalRootsQuery
204 crate::symbol_index::LibraryRootsQuery
207 crate::LineIndexQuery
210 // To collect interned data, we need to bump the revision counter by performing a synthetic
212 // We do this after collecting the non-interned queries to correctly attribute memory used
214 self.salsa_runtime_mut().synthetic_write(Durability::HIGH);
218 hir::db::InternMacroQuery
219 hir::db::InternEagerExpansionQuery
222 hir::db::InternFunctionQuery
223 hir::db::InternStructQuery
224 hir::db::InternUnionQuery
225 hir::db::InternEnumQuery
226 hir::db::InternConstQuery
227 hir::db::InternStaticQuery
228 hir::db::InternTraitQuery
229 hir::db::InternTypeAliasQuery
230 hir::db::InternImplQuery
233 hir::db::InternTypeParamIdQuery
236 acc.sort_by_key(|it| std::cmp::Reverse(it.1));