mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 15:14:32 +00:00
automatically collect garbage
This commit is contained in:
parent
19f77603c0
commit
7801f6b50f
8 changed files with 75 additions and 25 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -890,7 +890,7 @@ dependencies = [
|
||||||
"ra_syntax 0.1.0",
|
"ra_syntax 0.1.0",
|
||||||
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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",
|
"test_utils 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1267,7 +1267,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa"
|
name = "salsa"
|
||||||
version = "0.10.0-alpha5"
|
version = "0.10.0-alpha5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa-macros"
|
name = "salsa-macros"
|
||||||
version = "0.10.0-alpha5"
|
version = "0.10.0-alpha5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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 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 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 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 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 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"
|
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
|
|
|
@ -5,8 +5,8 @@ version = "0.1.0"
|
||||||
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
|
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
salsa = { path = "/home/matklad/projects/salsa" }
|
||||||
relative-path = "0.4.0"
|
relative-path = "0.4.0"
|
||||||
salsa = "0.10.0-alpha5"
|
|
||||||
rustc-hash = "1.0"
|
rustc-hash = "1.0"
|
||||||
parking_lot = "0.7.0"
|
parking_lot = "0.7.0"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::{
|
||||||
|
sync::Arc,
|
||||||
|
time,
|
||||||
|
};
|
||||||
|
|
||||||
use ra_db::{
|
use ra_db::{
|
||||||
CheckCanceled, FileId, Canceled, SourceDatabase,
|
CheckCanceled, FileId, Canceled, SourceDatabase,
|
||||||
|
@ -17,6 +20,8 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
|
||||||
pub(crate) struct RootDatabase {
|
pub(crate) struct RootDatabase {
|
||||||
runtime: salsa::Runtime<RootDatabase>,
|
runtime: salsa::Runtime<RootDatabase>,
|
||||||
interner: Arc<hir::HirInterner>,
|
interner: Arc<hir::HirInterner>,
|
||||||
|
pub(crate) last_gc: time::Instant,
|
||||||
|
pub(crate) last_gc_check: time::Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl salsa::Database for RootDatabase {
|
impl salsa::Database for RootDatabase {
|
||||||
|
@ -33,6 +38,8 @@ impl Default for RootDatabase {
|
||||||
let mut db = RootDatabase {
|
let mut db = RootDatabase {
|
||||||
runtime: salsa::Runtime::default(),
|
runtime: salsa::Runtime::default(),
|
||||||
interner: Default::default(),
|
interner: Default::default(),
|
||||||
|
last_gc: time::Instant::now(),
|
||||||
|
last_gc_check: time::Instant::now(),
|
||||||
};
|
};
|
||||||
db.set_crate_graph(Default::default());
|
db.set_crate_graph(Default::default());
|
||||||
db.set_local_roots(Default::default());
|
db.set_local_roots(Default::default());
|
||||||
|
@ -46,6 +53,8 @@ impl salsa::ParallelDatabase for RootDatabase {
|
||||||
salsa::Snapshot::new(RootDatabase {
|
salsa::Snapshot::new(RootDatabase {
|
||||||
runtime: self.runtime.snapshot(self),
|
runtime: self.runtime.snapshot(self),
|
||||||
interner: Arc::clone(&self.interner),
|
interner: Arc::clone(&self.interner),
|
||||||
|
last_gc: self.last_gc.clone(),
|
||||||
|
last_gc_check: self.last_gc_check.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::{
|
||||||
|
sync::Arc,
|
||||||
|
time,
|
||||||
|
};
|
||||||
|
|
||||||
use hir::{
|
use hir::{
|
||||||
self, Problem, source_binder
|
self, Problem, source_binder
|
||||||
|
@ -19,12 +22,14 @@ use crate::{
|
||||||
CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
|
CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
|
||||||
Query, RootChange, SourceChange, SourceFileEdit,
|
Query, RootChange, SourceChange, SourceFileEdit,
|
||||||
symbol_index::{FileSymbol, SymbolsDatabase},
|
symbol_index::{FileSymbol, SymbolsDatabase},
|
||||||
|
status::syntax_tree_stats
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
|
||||||
|
|
||||||
impl db::RootDatabase {
|
impl db::RootDatabase {
|
||||||
pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
|
pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
|
||||||
log::info!("apply_change {:?}", change);
|
log::info!("apply_change {:?}", change);
|
||||||
// self.gc_syntax_trees();
|
|
||||||
if !change.new_roots.is_empty() {
|
if !change.new_roots.is_empty() {
|
||||||
let mut local_roots = Vec::clone(&self.local_roots());
|
let mut local_roots = Vec::clone(&self.local_roots());
|
||||||
for (root_id, is_local) in change.new_roots {
|
for (root_id, is_local) in change.new_roots {
|
||||||
|
@ -72,18 +77,41 @@ impl db::RootDatabase {
|
||||||
self.set_source_root(root_id, Arc::new(source_root));
|
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
|
/// Ideally, we should call this function from time to time to collect heavy
|
||||||
/// syntax trees. However, if we actually do that, everything is recomputed
|
/// syntax trees. However, if we actually do that, everything is recomputed
|
||||||
/// for some reason. Needs investigation.
|
/// for some reason. Needs investigation.
|
||||||
pub(crate) fn collect_garbage(&mut self) {
|
pub(crate) fn collect_garbage(&mut self) {
|
||||||
self.query(ra_db::ParseQuery)
|
self.last_gc = time::Instant::now();
|
||||||
.sweep(SweepStrategy::default().discard_values());
|
|
||||||
self.query(hir::db::HirParseQuery)
|
let sweep = SweepStrategy::default()
|
||||||
.sweep(SweepStrategy::default().discard_values());
|
.discard_values()
|
||||||
self.query(hir::db::FileItemsQuery)
|
.discard_all_revisions();
|
||||||
.sweep(SweepStrategy::default().discard_values());
|
|
||||||
self.query(hir::db::FileItemQuery)
|
self.query(ra_db::ParseQuery).sweep(sweep.clone());
|
||||||
.sweep(SweepStrategy::default().discard_values());
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,10 @@ impl AnalysisHost {
|
||||||
self.db.apply_change(change)
|
self.db.apply_change(change)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn maybe_collect_garbage(&mut self) {
|
||||||
|
self.db.maybe_collect_garbage();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn collect_garbage(&mut self) {
|
pub fn collect_garbage(&mut self) {
|
||||||
self.db.collect_garbage();
|
self.db.collect_garbage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,13 @@ use crate::{
|
||||||
symbol_index::{SymbolIndex, LibrarySymbolsQuery},
|
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 {
|
pub(crate) fn status(db: &RootDatabase) -> String {
|
||||||
let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
|
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
|
let symbols_stats = db
|
||||||
.query(LibrarySymbolsQuery)
|
.query(LibrarySymbolsQuery)
|
||||||
.entries::<LibrarySymbolsStats>();
|
.entries::<LibrarySymbolsStats>();
|
||||||
|
@ -26,8 +30,12 @@ pub(crate) fn status(db: &RootDatabase) -> String {
|
||||||
interner.len()
|
interner.len()
|
||||||
};
|
};
|
||||||
format!(
|
format!(
|
||||||
"{}\n{}\n{}\nn_defs {}\n",
|
"{}\n{}\n{}\nn_defs {}\nGC {:?} seconds ago",
|
||||||
files_stats, symbols_stats, syntax_tree_stats, n_defs
|
files_stats,
|
||||||
|
symbols_stats,
|
||||||
|
syntax_tree_stats,
|
||||||
|
n_defs,
|
||||||
|
db.last_gc.elapsed().as_secs(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,9 +66,9 @@ impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SyntaxTreeStats {
|
pub(crate) struct SyntaxTreeStats {
|
||||||
total: usize,
|
total: usize,
|
||||||
retained: usize,
|
pub(crate) retained: usize,
|
||||||
retained_size: Bytes,
|
retained_size: Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,7 @@ fn main_loop_inner(
|
||||||
|
|
||||||
let (libdata_sender, libdata_receiver) = unbounded();
|
let (libdata_sender, libdata_receiver) = unbounded();
|
||||||
loop {
|
loop {
|
||||||
|
state.maybe_collect_garbage();
|
||||||
log::trace!("selecting");
|
log::trace!("selecting");
|
||||||
let event = select! {
|
let event = select! {
|
||||||
recv(msg_receiver) -> msg => match msg {
|
recv(msg_receiver) -> msg => match msg {
|
||||||
|
@ -207,7 +208,7 @@ fn main_loop_inner(
|
||||||
};
|
};
|
||||||
match req.cast::<req::CollectGarbage>() {
|
match req.cast::<req::CollectGarbage>() {
|
||||||
Ok((id, ())) => {
|
Ok((id, ())) => {
|
||||||
state.collect_garbadge();
|
state.collect_garbage();
|
||||||
let resp = RawResponse::ok::<req::CollectGarbage>(id, &());
|
let resp = RawResponse::ok::<req::CollectGarbage>(id, &());
|
||||||
msg_sender.send(RawMessage::Response(resp)).unwrap()
|
msg_sender.send(RawMessage::Response(resp)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,11 @@ impl ServerWorldState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
self.analysis_host.collect_garbage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue