]> git.lizzy.rs Git - rust.git/commitdiff
automatically collect garbage
authorAleksey Kladov <aleksey.kladov@gmail.com>
Sat, 26 Jan 2019 17:33:33 +0000 (20:33 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 27 Jan 2019 19:57:18 +0000 (22:57 +0300)
Cargo.lock
crates/ra_db/Cargo.toml
crates/ra_ide_api/src/db.rs
crates/ra_ide_api/src/imp.rs
crates/ra_ide_api/src/lib.rs
crates/ra_ide_api/src/status.rs
crates/ra_lsp_server/src/main_loop.rs
crates/ra_lsp_server/src/server_world.rs

index dc54edef6f3f8df9569ad643463cd66ac255e330..cbd4461c9ce8da5123e21656a0ae2fd16f26ea47 100644 (file)
@@ -890,7 +890,7 @@ dependencies = [
  "ra_syntax 0.1.0",
  "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "salsa 0.10.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "salsa 0.10.0-alpha5",
  "test_utils 0.1.0",
 ]
 
@@ -1267,7 +1267,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "salsa"
 version = "0.10.0-alpha5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1275,14 +1274,13 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "salsa-macros 0.10.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "salsa-macros 0.10.0-alpha5",
  "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "salsa-macros"
 version = "0.10.0-alpha5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1950,8 +1948,6 @@ dependencies = [
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c"
 "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
-"checksum salsa 0.10.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)" = "8b5e2535d707dc5ced81106d3b71d806cfeef8a6e8a567472fde7ffd56b770dd"
-"checksum salsa-macros 0.10.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c5da4c649f6d4fc1864fcd9a379b1f7c6d570b278559c84a6e15981c949cc6"
 "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
index 2d39b77ed430716b12fa214a4f12be8d657986a8..e479b38a00242ab236a5617ba9d95bf6ee5885b3 100644 (file)
@@ -5,8 +5,8 @@ version = "0.1.0"
 authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
 
 [dependencies]
+salsa = { path = "/home/matklad/projects/salsa" }
 relative-path = "0.4.0"
-salsa = "0.10.0-alpha5"
 rustc-hash = "1.0"
 parking_lot = "0.7.0"
 
index 3da93ec35b68471740ca9cde80517634523187f4..6850811d75be46d51830b5f67e649552891fd604 100644 (file)
@@ -1,4 +1,7 @@
-use std::sync::Arc;
+use std::{
+    sync::Arc,
+    time,
+};
 
 use ra_db::{
     CheckCanceled, FileId, Canceled, SourceDatabase,
@@ -17,6 +20,8 @@
 pub(crate) struct RootDatabase {
     runtime: salsa::Runtime<RootDatabase>,
     interner: Arc<hir::HirInterner>,
+    pub(crate) last_gc: time::Instant,
+    pub(crate) last_gc_check: time::Instant,
 }
 
 impl salsa::Database for RootDatabase {
@@ -33,6 +38,8 @@ fn default() -> RootDatabase {
         let mut db = RootDatabase {
             runtime: salsa::Runtime::default(),
             interner: Default::default(),
+            last_gc: time::Instant::now(),
+            last_gc_check: time::Instant::now(),
         };
         db.set_crate_graph(Default::default());
         db.set_local_roots(Default::default());
@@ -46,6 +53,8 @@ fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
         salsa::Snapshot::new(RootDatabase {
             runtime: self.runtime.snapshot(self),
             interner: Arc::clone(&self.interner),
+            last_gc: self.last_gc.clone(),
+            last_gc_check: self.last_gc_check.clone(),
         })
     }
 }
index 399433a01b8786ca566b716307ac8c893f9b8d05..0dd3e8cb0eec804a6e02f6076554eeab67e51bf9 100644 (file)
@@ -1,4 +1,7 @@
-use std::sync::Arc;
+use std::{
+    sync::Arc,
+    time,
+};
 
 use hir::{
     self, Problem, source_binder
     CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
     Query, RootChange, SourceChange, SourceFileEdit,
     symbol_index::{FileSymbol, SymbolsDatabase},
+    status::syntax_tree_stats
 };
 
+const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
+
 impl db::RootDatabase {
     pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
         log::info!("apply_change {:?}", change);
-        // self.gc_syntax_trees();
         if !change.new_roots.is_empty() {
             let mut local_roots = Vec::clone(&self.local_roots());
             for (root_id, is_local) in change.new_roots {
@@ -72,18 +77,41 @@ fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange)
         self.set_source_root(root_id, Arc::new(source_root));
     }
 
+    pub(crate) fn maybe_collect_garbage(&mut self) {
+        if self.last_gc_check.elapsed() > GC_COOLDOWN {
+            self.last_gc_check = time::Instant::now();
+            let retained_trees = syntax_tree_stats(self).retained;
+            if retained_trees > 100 {
+                log::info!(
+                    "automatic garbadge collection, {} retained trees",
+                    retained_trees
+                );
+                self.collect_garbage();
+            }
+        }
+    }
+
     /// Ideally, we should call this function from time to time to collect heavy
     /// syntax trees. However, if we actually do that, everything is recomputed
     /// for some reason. Needs investigation.
     pub(crate) fn collect_garbage(&mut self) {
-        self.query(ra_db::ParseQuery)
-            .sweep(SweepStrategy::default().discard_values());
-        self.query(hir::db::HirParseQuery)
-            .sweep(SweepStrategy::default().discard_values());
-        self.query(hir::db::FileItemsQuery)
-            .sweep(SweepStrategy::default().discard_values());
-        self.query(hir::db::FileItemQuery)
-            .sweep(SweepStrategy::default().discard_values());
+        self.last_gc = time::Instant::now();
+
+        let sweep = SweepStrategy::default()
+            .discard_values()
+            .discard_all_revisions();
+
+        self.query(ra_db::ParseQuery).sweep(sweep.clone());
+
+        self.query(hir::db::HirParseQuery).sweep(sweep.clone());
+        self.query(hir::db::FileItemsQuery).sweep(sweep.clone());
+        self.query(hir::db::FileItemQuery).sweep(sweep.clone());
+
+        self.query(hir::db::LowerModuleQuery).sweep(sweep.clone());
+        self.query(hir::db::LowerModuleSourceMapQuery)
+            .sweep(sweep.clone());
+        self.query(hir::db::BodySyntaxMappingQuery)
+            .sweep(sweep.clone());
     }
 }
 
index 43c8bea71049a99b6bc87b3c341c915f8d39c84d..a7caac02d0f9d693beaa69d65bd8d4dde760eb8a 100644 (file)
@@ -286,6 +286,10 @@ pub fn apply_change(&mut self, change: AnalysisChange) {
         self.db.apply_change(change)
     }
 
+    pub fn maybe_collect_garbage(&mut self) {
+        self.db.maybe_collect_garbage();
+    }
+
     pub fn collect_garbage(&mut self) {
         self.db.collect_garbage();
     }
index e11eed223c10321570acfdf7a56b6d2fc852c9e3..0dde30ae017ddf43edafbe7a50634dad7c8735bf 100644 (file)
     symbol_index::{SymbolIndex, LibrarySymbolsQuery},
 };
 
+pub(crate) fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
+    db.query(ParseQuery).entries::<SyntaxTreeStats>()
+}
+
 pub(crate) fn status(db: &RootDatabase) -> String {
     let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
-    let syntax_tree_stats = db.query(ParseQuery).entries::<SyntaxTreeStats>();
+    let syntax_tree_stats = syntax_tree_stats(db);
     let symbols_stats = db
         .query(LibrarySymbolsQuery)
         .entries::<LibrarySymbolsStats>();
@@ -26,8 +30,12 @@ pub(crate) fn status(db: &RootDatabase) -> String {
         interner.len()
     };
     format!(
-        "{}\n{}\n{}\nn_defs {}\n",
-        files_stats, symbols_stats, syntax_tree_stats, n_defs
+        "{}\n{}\n{}\nn_defs {}\nGC {:?} seconds ago",
+        files_stats,
+        symbols_stats,
+        syntax_tree_stats,
+        n_defs,
+        db.last_gc.elapsed().as_secs(),
     )
 }
 
@@ -58,9 +66,9 @@ fn from_iter<T>(iter: T) -> FilesStats
 }
 
 #[derive(Default)]
-struct SyntaxTreeStats {
+pub(crate) struct SyntaxTreeStats {
     total: usize,
-    retained: usize,
+    pub(crate) retained: usize,
     retained_size: Bytes,
 }
 
index ddd20a41fc68ca84690d0b6d8ab72caff341ce5e..e430ac6dec0856c0dacf64864ab36fbddeaf42bb 100644 (file)
@@ -172,6 +172,7 @@ fn main_loop_inner(
 
     let (libdata_sender, libdata_receiver) = unbounded();
     loop {
+        state.maybe_collect_garbage();
         log::trace!("selecting");
         let event = select! {
             recv(msg_receiver) -> msg => match msg {
@@ -207,7 +208,7 @@ fn main_loop_inner(
                     };
                     match req.cast::<req::CollectGarbage>() {
                         Ok((id, ())) => {
-                            state.collect_garbadge();
+                            state.collect_garbage();
                             let resp = RawResponse::ok::<req::CollectGarbage>(id, &());
                             msg_sender.send(RawMessage::Response(resp)).unwrap()
                         }
index bf04f1125eedf294be09ae6c5e8d0e79c438fd8a..c2167c5d80342c69a2eb283accdfd45f9c4a0eb0 100644 (file)
@@ -232,7 +232,11 @@ pub fn snapshot(&self) -> ServerWorld {
         }
     }
 
-    pub fn collect_garbadge(&mut self) {
+    pub fn maybe_collect_garbage(&mut self) {
+        self.analysis_host.maybe_collect_garbage()
+    }
+
+    pub fn collect_garbage(&mut self) {
         self.analysis_host.collect_garbage()
     }
 }