diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/db.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide_api/src/imp.rs | 48 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/status.rs | 18 |
4 files changed, 65 insertions, 16 deletions
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index 3da93ec35..6850811d7 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::{ |
2 | sync::Arc, | ||
3 | time, | ||
4 | }; | ||
2 | 5 | ||
3 | use ra_db::{ | 6 | use ra_db::{ |
4 | CheckCanceled, FileId, Canceled, SourceDatabase, | 7 | CheckCanceled, FileId, Canceled, SourceDatabase, |
@@ -17,6 +20,8 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}}; | |||
17 | pub(crate) struct RootDatabase { | 20 | pub(crate) struct RootDatabase { |
18 | runtime: salsa::Runtime<RootDatabase>, | 21 | runtime: salsa::Runtime<RootDatabase>, |
19 | interner: Arc<hir::HirInterner>, | 22 | interner: Arc<hir::HirInterner>, |
23 | pub(crate) last_gc: time::Instant, | ||
24 | pub(crate) last_gc_check: time::Instant, | ||
20 | } | 25 | } |
21 | 26 | ||
22 | impl salsa::Database for RootDatabase { | 27 | impl salsa::Database for RootDatabase { |
@@ -33,6 +38,8 @@ impl Default for RootDatabase { | |||
33 | let mut db = RootDatabase { | 38 | let mut db = RootDatabase { |
34 | runtime: salsa::Runtime::default(), | 39 | runtime: salsa::Runtime::default(), |
35 | interner: Default::default(), | 40 | interner: Default::default(), |
41 | last_gc: time::Instant::now(), | ||
42 | last_gc_check: time::Instant::now(), | ||
36 | }; | 43 | }; |
37 | db.set_crate_graph(Default::default()); | 44 | db.set_crate_graph(Default::default()); |
38 | db.set_local_roots(Default::default()); | 45 | db.set_local_roots(Default::default()); |
@@ -46,6 +53,8 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
46 | salsa::Snapshot::new(RootDatabase { | 53 | salsa::Snapshot::new(RootDatabase { |
47 | runtime: self.runtime.snapshot(self), | 54 | runtime: self.runtime.snapshot(self), |
48 | interner: Arc::clone(&self.interner), | 55 | interner: Arc::clone(&self.interner), |
56 | last_gc: self.last_gc.clone(), | ||
57 | last_gc_check: self.last_gc_check.clone(), | ||
49 | }) | 58 | }) |
50 | } | 59 | } |
51 | } | 60 | } |
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs index 399433a01..0dd3e8cb0 100644 --- a/crates/ra_ide_api/src/imp.rs +++ b/crates/ra_ide_api/src/imp.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::{ |
2 | sync::Arc, | ||
3 | time, | ||
4 | }; | ||
2 | 5 | ||
3 | use hir::{ | 6 | use hir::{ |
4 | self, Problem, source_binder | 7 | self, Problem, source_binder |
@@ -19,12 +22,14 @@ use crate::{ | |||
19 | CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, | 22 | CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, |
20 | Query, RootChange, SourceChange, SourceFileEdit, | 23 | Query, RootChange, SourceChange, SourceFileEdit, |
21 | symbol_index::{FileSymbol, SymbolsDatabase}, | 24 | symbol_index::{FileSymbol, SymbolsDatabase}, |
25 | status::syntax_tree_stats | ||
22 | }; | 26 | }; |
23 | 27 | ||
28 | const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); | ||
29 | |||
24 | impl db::RootDatabase { | 30 | impl db::RootDatabase { |
25 | pub(crate) fn apply_change(&mut self, change: AnalysisChange) { | 31 | pub(crate) fn apply_change(&mut self, change: AnalysisChange) { |
26 | log::info!("apply_change {:?}", change); | 32 | log::info!("apply_change {:?}", change); |
27 | // self.gc_syntax_trees(); | ||
28 | if !change.new_roots.is_empty() { | 33 | if !change.new_roots.is_empty() { |
29 | let mut local_roots = Vec::clone(&self.local_roots()); | 34 | let mut local_roots = Vec::clone(&self.local_roots()); |
30 | for (root_id, is_local) in change.new_roots { | 35 | for (root_id, is_local) in change.new_roots { |
@@ -72,18 +77,41 @@ impl db::RootDatabase { | |||
72 | self.set_source_root(root_id, Arc::new(source_root)); | 77 | self.set_source_root(root_id, Arc::new(source_root)); |
73 | } | 78 | } |
74 | 79 | ||
80 | pub(crate) fn maybe_collect_garbage(&mut self) { | ||
81 | if self.last_gc_check.elapsed() > GC_COOLDOWN { | ||
82 | self.last_gc_check = time::Instant::now(); | ||
83 | let retained_trees = syntax_tree_stats(self).retained; | ||
84 | if retained_trees > 100 { | ||
85 | log::info!( | ||
86 | "automatic garbadge collection, {} retained trees", | ||
87 | retained_trees | ||
88 | ); | ||
89 | self.collect_garbage(); | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
75 | /// Ideally, we should call this function from time to time to collect heavy | 94 | /// Ideally, we should call this function from time to time to collect heavy |
76 | /// syntax trees. However, if we actually do that, everything is recomputed | 95 | /// syntax trees. However, if we actually do that, everything is recomputed |
77 | /// for some reason. Needs investigation. | 96 | /// for some reason. Needs investigation. |
78 | pub(crate) fn collect_garbage(&mut self) { | 97 | pub(crate) fn collect_garbage(&mut self) { |
79 | self.query(ra_db::ParseQuery) | 98 | self.last_gc = time::Instant::now(); |
80 | .sweep(SweepStrategy::default().discard_values()); | 99 | |
81 | self.query(hir::db::HirParseQuery) | 100 | let sweep = SweepStrategy::default() |
82 | .sweep(SweepStrategy::default().discard_values()); | 101 | .discard_values() |
83 | self.query(hir::db::FileItemsQuery) | 102 | .discard_all_revisions(); |
84 | .sweep(SweepStrategy::default().discard_values()); | 103 | |
85 | self.query(hir::db::FileItemQuery) | 104 | self.query(ra_db::ParseQuery).sweep(sweep.clone()); |
86 | .sweep(SweepStrategy::default().discard_values()); | 105 | |
106 | self.query(hir::db::HirParseQuery).sweep(sweep.clone()); | ||
107 | self.query(hir::db::FileItemsQuery).sweep(sweep.clone()); | ||
108 | self.query(hir::db::FileItemQuery).sweep(sweep.clone()); | ||
109 | |||
110 | self.query(hir::db::LowerModuleQuery).sweep(sweep.clone()); | ||
111 | self.query(hir::db::LowerModuleSourceMapQuery) | ||
112 | .sweep(sweep.clone()); | ||
113 | self.query(hir::db::BodySyntaxMappingQuery) | ||
114 | .sweep(sweep.clone()); | ||
87 | } | 115 | } |
88 | } | 116 | } |
89 | 117 | ||
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 43c8bea71..a7caac02d 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -286,6 +286,10 @@ impl AnalysisHost { | |||
286 | self.db.apply_change(change) | 286 | self.db.apply_change(change) |
287 | } | 287 | } |
288 | 288 | ||
289 | pub fn maybe_collect_garbage(&mut self) { | ||
290 | self.db.maybe_collect_garbage(); | ||
291 | } | ||
292 | |||
289 | pub fn collect_garbage(&mut self) { | 293 | pub fn collect_garbage(&mut self) { |
290 | self.db.collect_garbage(); | 294 | self.db.collect_garbage(); |
291 | } | 295 | } |
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs index e11eed223..0dde30ae0 100644 --- a/crates/ra_ide_api/src/status.rs +++ b/crates/ra_ide_api/src/status.rs | |||
@@ -15,9 +15,13 @@ use crate::{ | |||
15 | symbol_index::{SymbolIndex, LibrarySymbolsQuery}, | 15 | symbol_index::{SymbolIndex, LibrarySymbolsQuery}, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub(crate) fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { | ||
19 | db.query(ParseQuery).entries::<SyntaxTreeStats>() | ||
20 | } | ||
21 | |||
18 | pub(crate) fn status(db: &RootDatabase) -> String { | 22 | pub(crate) fn status(db: &RootDatabase) -> String { |
19 | let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); | 23 | let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); |
20 | let syntax_tree_stats = db.query(ParseQuery).entries::<SyntaxTreeStats>(); | 24 | let syntax_tree_stats = syntax_tree_stats(db); |
21 | let symbols_stats = db | 25 | let symbols_stats = db |
22 | .query(LibrarySymbolsQuery) | 26 | .query(LibrarySymbolsQuery) |
23 | .entries::<LibrarySymbolsStats>(); | 27 | .entries::<LibrarySymbolsStats>(); |
@@ -26,8 +30,12 @@ pub(crate) fn status(db: &RootDatabase) -> String { | |||
26 | interner.len() | 30 | interner.len() |
27 | }; | 31 | }; |
28 | format!( | 32 | format!( |
29 | "{}\n{}\n{}\nn_defs {}\n", | 33 | "{}\n{}\n{}\nn_defs {}\nGC {:?} seconds ago", |
30 | files_stats, symbols_stats, syntax_tree_stats, n_defs | 34 | files_stats, |
35 | symbols_stats, | ||
36 | syntax_tree_stats, | ||
37 | n_defs, | ||
38 | db.last_gc.elapsed().as_secs(), | ||
31 | ) | 39 | ) |
32 | } | 40 | } |
33 | 41 | ||
@@ -58,9 +66,9 @@ impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats { | |||
58 | } | 66 | } |
59 | 67 | ||
60 | #[derive(Default)] | 68 | #[derive(Default)] |
61 | struct SyntaxTreeStats { | 69 | pub(crate) struct SyntaxTreeStats { |
62 | total: usize, | 70 | total: usize, |
63 | retained: usize, | 71 | pub(crate) retained: usize, |
64 | retained_size: Bytes, | 72 | retained_size: Bytes, |
65 | } | 73 | } |
66 | 74 | ||