diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2023-04-22 09:34:47 +0200 |
|---|---|---|
| committer | Lukas Wirth <lukastw97@gmail.com> | 2023-04-22 09:34:47 +0200 |
| commit | 63e3bf118d69f128f17508da9065b436be6da3c2 (patch) | |
| tree | 6d222d92c48662bbb89b93f5a8934a5a29e88142 | |
| parent | e7285507f64c1b63e83cb38a2d005fdab5ff7387 (diff) | |
| download | rust-63e3bf118d69f128f17508da9065b436be6da3c2.tar.gz rust-63e3bf118d69f128f17508da9065b436be6da3c2.zip | |
internal: Add some additional status ouput
| -rw-r--r-- | crates/ide/src/status.rs | 241 | ||||
| -rw-r--r-- | crates/profile/src/memory_usage.rs | 6 |
2 files changed, 175 insertions, 72 deletions
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index 71fc91cf317..116e6b9751c 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs @@ -1,9 +1,18 @@ -use std::{fmt, sync::Arc}; +use std::{fmt, marker::PhantomData, sync::Arc}; -use hir::{ExpandResult, MacroFile}; -use ide_db::base_db::{ - salsa::debug::{DebugQueryTable, TableEntry}, - CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId, +use hir::{ + db::{AstIdMapQuery, AttrsQuery, ParseMacroExpansionQuery}, + Attr, Attrs, ExpandResult, MacroFile, Module, +}; +use ide_db::{ + base_db::{ + salsa::{ + debug::{DebugQueryTable, TableEntry}, + Query, QueryTable, + }, + CrateId, FileId, FileTextQuery, ParseQuery, SourceDatabase, SourceRootId, + }, + symbol_index::ModuleSymbolsQuery, }; use ide_db::{ symbol_index::{LibrarySymbolsQuery, SymbolIndex}, @@ -15,13 +24,6 @@ use std::env; use stdx::format_to; use syntax::{ast, Parse, SyntaxNode}; -fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { - ide_db::base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>() -} -fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { - hir::db::ParseMacroExpansionQuery.in_db(db).entries::<SyntaxTreeStats>() -} - // Feature: Status // // Shows internal statistic about memory usage of rust-analyzer. @@ -34,15 +36,21 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { // image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[] pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { let mut buf = String::new(); - format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>()); - format_to!(buf, "{}\n", LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>()); - format_to!(buf, "{}\n", syntax_tree_stats(db)); - format_to!(buf, "{} (Macros)\n", macro_syntax_tree_stats(db)); + + format_to!(buf, "{}\n", collect_query(FileTextQuery.in_db(db))); + format_to!(buf, "{}\n", collect_query(ParseQuery.in_db(db))); + format_to!(buf, "{}\n", collect_query(ParseMacroExpansionQuery.in_db(db))); + format_to!(buf, "{}\n", collect_query(LibrarySymbolsQuery.in_db(db))); + format_to!(buf, "{}\n", collect_query(ModuleSymbolsQuery.in_db(db))); format_to!(buf, "{} in total\n", memory_usage()); if env::var("RA_COUNT").is_ok() { format_to!(buf, "\nCounts:\n{}", profile::countme::get_all()); } + format_to!(buf, "\nDebug info:\n"); + format_to!(buf, "{}\n", collect_query(AttrsQuery.in_db(db))); + format_to!(buf, "{} ast id maps\n", collect_query_count(AstIdMapQuery.in_db(db))); + if let Some(file_id) = file_id { format_to!(buf, "\nFile info:\n"); let crates = crate::parent_module::crates_for(db, file_id); @@ -52,8 +60,8 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { let crate_graph = db.crate_graph(); for krate in crates { let display_crate = |krate: CrateId| match &crate_graph[krate].display_name { - Some(it) => format!("{it}({krate:?})"), - None => format!("{krate:?}"), + Some(it) => format!("{it}({})", krate.into_raw()), + None => format!("{}", krate.into_raw()), }; format_to!(buf, "Crate: {}\n", display_crate(krate)); let deps = crate_graph[krate] @@ -68,6 +76,82 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { buf.trim().to_string() } +fn collect_query<'q, Q>(table: QueryTable<'q, Q>) -> <Q as QueryCollect>::Collector +where + QueryTable<'q, Q>: DebugQueryTable, + Q: QueryCollect, + <Q as Query>::Storage: 'q, + <Q as QueryCollect>::Collector: StatCollect< + <QueryTable<'q, Q> as DebugQueryTable>::Key, + <QueryTable<'q, Q> as DebugQueryTable>::Value, + >, +{ + struct StatCollectorWrapper<C>(C); + impl<C: StatCollect<K, V>, K, V> FromIterator<TableEntry<K, V>> for StatCollectorWrapper<C> { + fn from_iter<T>(iter: T) -> StatCollectorWrapper<C> + where + T: IntoIterator<Item = TableEntry<K, V>>, + { + let mut res = C::default(); + for entry in iter { + res.collect_entry(entry.key, entry.value); + } + StatCollectorWrapper(res) + } + } + table.entries::<StatCollectorWrapper<<Q as QueryCollect>::Collector>>().0 +} + +fn collect_query_count<'q, Q>(table: QueryTable<'q, Q>) -> usize +where + QueryTable<'q, Q>: DebugQueryTable, + Q: Query, + <Q as Query>::Storage: 'q, +{ + struct EntryCounter(usize); + impl<K, V> FromIterator<TableEntry<K, V>> for EntryCounter { + fn from_iter<T>(iter: T) -> EntryCounter + where + T: IntoIterator<Item = TableEntry<K, V>>, + { + EntryCounter(iter.into_iter().count()) + } + } + table.entries::<EntryCounter>().0 +} + +trait QueryCollect: Query { + type Collector; +} + +impl QueryCollect for LibrarySymbolsQuery { + type Collector = SymbolsStats<SourceRootId>; +} + +impl QueryCollect for ParseQuery { + type Collector = SyntaxTreeStats<false>; +} + +impl QueryCollect for ParseMacroExpansionQuery { + type Collector = SyntaxTreeStats<true>; +} + +impl QueryCollect for FileTextQuery { + type Collector = FilesStats; +} + +impl QueryCollect for ModuleSymbolsQuery { + type Collector = SymbolsStats<Module>; +} + +impl QueryCollect for AttrsQuery { + type Collector = AttrsStats; +} + +trait StatCollect<K, V>: Default { + fn collect_entry(&mut self, key: K, value: Option<V>); +} + #[derive(Default)] struct FilesStats { total: usize, @@ -80,85 +164,98 @@ impl fmt::Display for FilesStats { } } -impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats { - fn from_iter<T>(iter: T) -> FilesStats - where - T: IntoIterator<Item = TableEntry<FileId, Arc<String>>>, - { - let mut res = FilesStats::default(); - for entry in iter { - res.total += 1; - res.size += entry.value.unwrap().len(); - } - res +impl StatCollect<FileId, Arc<String>> for FilesStats { + fn collect_entry(&mut self, _: FileId, value: Option<Arc<String>>) { + self.total += 1; + self.size += value.unwrap().len(); } } #[derive(Default)] -pub(crate) struct SyntaxTreeStats { +pub(crate) struct SyntaxTreeStats<const MACROS: bool> { total: usize, pub(crate) retained: usize, } -impl fmt::Display for SyntaxTreeStats { +impl<const MACROS: bool> fmt::Display for SyntaxTreeStats<MACROS> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{} trees, {} preserved", self.total, self.retained) + write!( + fmt, + "{} trees, {} preserved{}", + self.total, + self.retained, + if MACROS { " (macros)" } else { "" } + ) } } -impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStats { - fn from_iter<T>(iter: T) -> SyntaxTreeStats - where - T: IntoIterator<Item = TableEntry<FileId, Parse<ast::SourceFile>>>, - { - let mut res = SyntaxTreeStats::default(); - for entry in iter { - res.total += 1; - res.retained += entry.value.is_some() as usize; - } - res +impl StatCollect<FileId, Parse<ast::SourceFile>> for SyntaxTreeStats<false> { + fn collect_entry(&mut self, _: FileId, value: Option<Parse<ast::SourceFile>>) { + self.total += 1; + self.retained += value.is_some() as usize; } } -impl<M> FromIterator<TableEntry<MacroFile, ExpandResult<(Parse<SyntaxNode>, M)>>> - for SyntaxTreeStats -{ - fn from_iter<T>(iter: T) -> SyntaxTreeStats - where - T: IntoIterator<Item = TableEntry<MacroFile, ExpandResult<(Parse<SyntaxNode>, M)>>>, - { - let mut res = SyntaxTreeStats::default(); - for entry in iter { - res.total += 1; - res.retained += entry.value.is_some() as usize; - } - res +impl<M> StatCollect<MacroFile, ExpandResult<(Parse<SyntaxNode>, M)>> for SyntaxTreeStats<true> { + fn collect_entry(&mut self, _: MacroFile, value: Option<ExpandResult<(Parse<SyntaxNode>, M)>>) { + self.total += 1; + self.retained += value.is_some() as usize; } } -#[derive(Default)] -struct LibrarySymbolsStats { +struct SymbolsStats<Key> { total: usize, size: Bytes, + phantom: PhantomData<Key>, } -impl fmt::Display for LibrarySymbolsStats { +impl<Key> Default for SymbolsStats<Key> { + fn default() -> Self { + Self { total: Default::default(), size: Default::default(), phantom: PhantomData } + } +} + +impl fmt::Display for SymbolsStats<Module> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{} of index symbols ({})", self.size, self.total) + write!(fmt, "{} of module index symbols ({})", self.size, self.total) + } +} +impl fmt::Display for SymbolsStats<SourceRootId> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{} of library index symbols ({})", self.size, self.total) + } +} +impl<Key> StatCollect<Key, Arc<SymbolIndex>> for SymbolsStats<Key> { + fn collect_entry(&mut self, _: Key, value: Option<Arc<SymbolIndex>>) { + let symbols = value.unwrap(); + self.total += symbols.len(); + self.size += symbols.memory_size(); } } -impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbolsStats { - fn from_iter<T>(iter: T) -> LibrarySymbolsStats - where - T: IntoIterator<Item = TableEntry<SourceRootId, Arc<SymbolIndex>>>, - { - let mut res = LibrarySymbolsStats::default(); - for entry in iter { - let symbols = entry.value.unwrap(); - res.total += symbols.len(); - res.size += symbols.memory_size(); - } - res +#[derive(Default)] +struct AttrsStats { + entries: usize, + total: usize, +} + +impl fmt::Display for AttrsStats { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let size = + self.entries * std::mem::size_of::<Attrs>() + self.total * std::mem::size_of::<Attr>(); + let size = Bytes::new(size as _); + write!( + fmt, + "{} attribute query entries, {} total attributes ({} for storing entries)", + self.entries, self.total, size + ) + } +} + +impl<Key> StatCollect<Key, Attrs> for AttrsStats { + fn collect_entry(&mut self, _: Key, value: Option<Attrs>) { + let attrs = value.unwrap(); + self.entries += 1; + self.total += attrs.len(); } } diff --git a/crates/profile/src/memory_usage.rs b/crates/profile/src/memory_usage.rs index 8017f865792..f089c78e0c1 100644 --- a/crates/profile/src/memory_usage.rs +++ b/crates/profile/src/memory_usage.rs @@ -91,6 +91,12 @@ fn memusage_linux() -> MemoryUsage { pub struct Bytes(isize); impl Bytes { + pub fn new(bytes: isize) -> Bytes { + Bytes(bytes) + } +} + +impl Bytes { pub fn megabytes(self) -> isize { self.0 / 1024 / 1024 } |
