diff options
-rw-r--r-- | crates/ra_cli/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_cli/src/analysis_stats.rs | 11 | ||||
-rw-r--r-- | crates/ra_cli/src/main.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/change.rs | 63 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_prof/src/memory_usage.rs | 27 |
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] |
21 | path = "../ra_prof" | 21 | path = "../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 | ||
7 | use crate::Result; | 7 | use crate::Result; |
8 | 8 | ||
9 | pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> { | 9 | pub 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 { | |||
57 | pub trait AstDatabase: InternDatabase { | 57 | pub 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 | }; |
11 | use ra_syntax::SourceFile; | 11 | use ra_syntax::SourceFile; |
12 | use ra_prof::profile; | 12 | use ra_prof::{profile, Bytes, memory_usage}; |
13 | use relative_path::RelativePathBuf; | 13 | use relative_path::RelativePathBuf; |
14 | use rayon::prelude::*; | 14 | use 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)] |
31 | pub struct Bytes(usize); | 31 | pub struct Bytes(usize); |
32 | 32 | ||
33 | impl fmt::Display for Bytes { | 33 | impl 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 | |||
56 | impl std::ops::Sub for Bytes { | ||
57 | type Output = Bytes; | ||
58 | fn sub(self, rhs: Bytes) -> Bytes { | ||
59 | Bytes(self.0 - rhs.0) | ||
60 | } | ||
61 | } | ||