aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_cli/Cargo.toml1
-rw-r--r--crates/ra_cli/src/analysis_stats.rs11
-rw-r--r--crates/ra_cli/src/main.rs4
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_ide_api/src/change.rs63
-rw-r--r--crates/ra_ide_api/src/lib.rs4
-rw-r--r--crates/ra_prof/src/memory_usage.rs27
7 files changed, 101 insertions, 13 deletions
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index b10873cd8..639b7c949 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -20,3 +20,4 @@ ra_db = { path = "../ra_db" }
20[dependencies.ra_prof] 20[dependencies.ra_prof]
21path = "../ra_prof" 21path = "../ra_prof"
22# features = [ "cpuprofiler" ] 22# features = [ "cpuprofiler" ]
23# features = [ "jemalloc" ]
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 2eaf784a6..a01c07c3f 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -6,9 +6,9 @@ use ra_syntax::AstNode;
6 6
7use crate::Result; 7use crate::Result;
8 8
9pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> { 9pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -> Result<()> {
10 let db_load_time = Instant::now(); 10 let db_load_time = Instant::now();
11 let (host, roots) = ra_batch::load_cargo(path)?; 11 let (mut host, roots) = ra_batch::load_cargo(path)?;
12 let db = host.raw_database(); 12 let db = host.raw_database();
13 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); 13 println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
14 let analysis_time = Instant::now(); 14 let analysis_time = Instant::now();
@@ -113,5 +113,12 @@ pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> {
113 (num_exprs_partially_unknown * 100 / num_exprs) 113 (num_exprs_partially_unknown * 100 / num_exprs)
114 ); 114 );
115 println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); 115 println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
116
117 if memory_usage {
118 for (name, bytes) in host.per_query_memory_usage() {
119 println!("{:>8} {}", bytes, name)
120 }
121 }
122
116 Ok(()) 123 Ok(())
117} 124}
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 5adf8b096..d2f6544f8 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -24,6 +24,7 @@ fn main() -> Result<()> {
24 .subcommand( 24 .subcommand(
25 SubCommand::with_name("analysis-stats") 25 SubCommand::with_name("analysis-stats")
26 .arg(Arg::with_name("verbose").short("v").long("verbose")) 26 .arg(Arg::with_name("verbose").short("v").long("verbose"))
27 .arg(Arg::with_name("memory-usage").long("memory-usage"))
27 .arg(Arg::with_name("only").short("o").takes_value(true)) 28 .arg(Arg::with_name("only").short("o").takes_value(true))
28 .arg(Arg::with_name("path")), 29 .arg(Arg::with_name("path")),
29 ) 30 )
@@ -71,9 +72,10 @@ fn main() -> Result<()> {
71 } 72 }
72 ("analysis-stats", Some(matches)) => { 73 ("analysis-stats", Some(matches)) => {
73 let verbose = matches.is_present("verbose"); 74 let verbose = matches.is_present("verbose");
75 let memory_usage = matches.is_present("memory-usage");
74 let path = matches.value_of("path").unwrap_or(""); 76 let path = matches.value_of("path").unwrap_or("");
75 let only = matches.value_of("only"); 77 let only = matches.value_of("only");
76 analysis_stats::run(verbose, path.as_ref(), only)?; 78 analysis_stats::run(verbose, memory_usage, path.as_ref(), only)?;
77 } 79 }
78 ("analysis-bench", Some(matches)) => { 80 ("analysis-bench", Some(matches)) => {
79 let verbose = matches.is_present("verbose"); 81 let verbose = matches.is_present("verbose");
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 8f4de1c85..b7d5ab5c6 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -57,17 +57,21 @@ pub trait InternDatabase: SourceDatabase {
57pub trait AstDatabase: InternDatabase { 57pub trait AstDatabase: InternDatabase {
58 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] 58 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
59 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; 59 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
60
60 #[salsa::transparent] 61 #[salsa::transparent]
61 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)] 62 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
62 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>; 63 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
64
63 #[salsa::transparent] 65 #[salsa::transparent]
64 #[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)] 66 #[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)]
65 fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>; 67 fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>;
68
66 #[salsa::invoke(crate::ids::HirFileId::parse_macro_query)] 69 #[salsa::invoke(crate::ids::HirFileId::parse_macro_query)]
67 fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<TreeArc<SyntaxNode>>; 70 fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<TreeArc<SyntaxNode>>;
68 71
69 #[salsa::invoke(crate::ids::macro_def_query)] 72 #[salsa::invoke(crate::ids::macro_def_query)]
70 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 73 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
74
71 #[salsa::invoke(crate::ids::macro_arg_query)] 75 #[salsa::invoke(crate::ids::macro_arg_query)]
72 fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>; 76 fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>;
73 77
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 8d9918d16..2dfedad01 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -9,7 +9,7 @@ use ra_db::{
9 salsa::{Database, SweepStrategy}, 9 salsa::{Database, SweepStrategy},
10}; 10};
11use ra_syntax::SourceFile; 11use ra_syntax::SourceFile;
12use ra_prof::profile; 12use ra_prof::{profile, Bytes, memory_usage};
13use relative_path::RelativePathBuf; 13use relative_path::RelativePathBuf;
14use rayon::prelude::*; 14use rayon::prelude::*;
15 15
@@ -243,4 +243,65 @@ impl RootDatabase {
243 self.query(hir::db::InferQuery).sweep(sweep); 243 self.query(hir::db::InferQuery).sweep(sweep);
244 self.query(hir::db::BodyHirQuery).sweep(sweep); 244 self.query(hir::db::BodyHirQuery).sweep(sweep);
245 } 245 }
246
247 pub(crate) fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
248 let mut acc: Vec<(String, Bytes)> = vec![];
249 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
250 macro_rules! sweep_each_query {
251 ($($q:path)*) => {$(
252 let before = memory_usage().allocated;
253 self.query($q).sweep(sweep);
254 let after = memory_usage().allocated;
255 let q: $q = Default::default();
256 let name = format!("{:?}", q);
257 acc.push((name, before - after));
258 )*}
259 }
260 sweep_each_query![
261 ra_db::ParseQuery
262 ra_db::SourceRootCratesQuery
263 hir::db::AstIdMapQuery
264 hir::db::ParseMacroQuery
265 hir::db::MacroDefQuery
266 hir::db::MacroArgQuery
267 hir::db::MacroExpandQuery
268 hir::db::StructDataQuery
269 hir::db::EnumDataQuery
270 hir::db::TraitDataQuery
271 hir::db::TraitItemsIndexQuery
272 hir::db::RawItemsQuery
273 hir::db::RawItemsWithSourceMapQuery
274 hir::db::CrateDefMapQuery
275 hir::db::ImplsInModuleQuery
276 hir::db::ImplsInModuleWithSourceMapQuery
277 hir::db::GenericParamsQuery
278 hir::db::FnDataQuery
279 hir::db::TypeAliasDataQuery
280 hir::db::ConstDataQuery
281 hir::db::StaticDataQuery
282 hir::db::ModuleLangItemsQuery
283 hir::db::LangItemsQuery
284 hir::db::LangItemQuery
285 hir::db::DocumentationQuery
286 hir::db::ExprScopesQuery
287 hir::db::InferQuery
288 hir::db::TypeForDefQuery
289 hir::db::TypeForFieldQuery
290 hir::db::CallableItemSignatureQuery
291 hir::db::GenericPredicatesQuery
292 hir::db::GenericDefaultsQuery
293 hir::db::BodyWithSourceMapQuery
294 hir::db::BodyHirQuery
295 hir::db::ImplsInCrateQuery
296 hir::db::ImplsForTraitQuery
297 hir::db::AssociatedTyDataQuery
298 hir::db::TraitDatumQuery
299 hir::db::StructDatumQuery
300 hir::db::ImplDatumQuery
301 hir::db::ImplementsQuery
302 hir::db::NormalizeQuery
303 ];
304 acc.sort_by_key(|it| std::cmp::Reverse(it.1));
305 acc
306 }
246} 307}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 28a74c003..817e65df0 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -270,6 +270,10 @@ impl AnalysisHost {
270 pub fn collect_garbage(&mut self) { 270 pub fn collect_garbage(&mut self) {
271 self.db.collect_garbage(); 271 self.db.collect_garbage();
272 } 272 }
273 /// NB: this clears the database
274 pub fn per_query_memory_usage(&mut self) -> Vec<(String, ra_prof::Bytes)> {
275 self.db.per_query_memory_usage()
276 }
273 pub fn raw_database(&self) -> &(impl hir::db::HirDatabase + salsa::Database) { 277 pub fn raw_database(&self) -> &(impl hir::db::HirDatabase + salsa::Database) {
274 &self.db 278 &self.db
275 } 279 }
diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs
index 2bde8fb5f..7f857942d 100644
--- a/crates/ra_prof/src/memory_usage.rs
+++ b/crates/ra_prof/src/memory_usage.rs
@@ -27,21 +27,23 @@ impl fmt::Display for MemoryUsage {
27 } 27 }
28} 28}
29 29
30#[derive(Default)] 30#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
31pub struct Bytes(usize); 31pub struct Bytes(usize);
32 32
33impl fmt::Display for Bytes { 33impl fmt::Display for Bytes {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 let bytes = self.0; 35 let bytes = self.0;
36 if bytes < 4096 { 36 let mut value = bytes;
37 return write!(f, "{} bytes", bytes); 37 let mut suffix = "b";
38 if value > 4096 {
39 value /= 1024;
40 suffix = "kb";
41 if value > 4096 {
42 value /= 1024;
43 suffix = "mb";
44 }
38 } 45 }
39 let kb = bytes / 1024; 46 f.pad(&format!("{}{}", value, suffix))
40 if kb < 4096 {
41 return write!(f, "{}kb", kb);
42 }
43 let mb = kb / 1024;
44 write!(f, "{}mb", mb)
45 } 47 }
46} 48}
47 49
@@ -50,3 +52,10 @@ impl std::ops::AddAssign<usize> for Bytes {
50 self.0 += x; 52 self.0 += x;
51 } 53 }
52} 54}
55
56impl std::ops::Sub for Bytes {
57 type Output = Bytes;
58 fn sub(self, rhs: Bytes) -> Bytes {
59 Bytes(self.0 - rhs.0)
60 }
61}