Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/status.rs')
-rw-r--r--crates/ide/src/status.rs241
1 files changed, 170 insertions, 71 deletions
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index 7ce782f93b..d2c77e2dc7 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};
-use hir::{ExpandResult, MacroFile};
-use ide_db::base_db::{
- salsa::debug::{DebugQueryTable, TableEntry},
- CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId,
+use hir::{
+ db::{AstIdMapQuery, AttrsQuery, BlockDefMapQuery, 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},
@@ -14,13 +23,7 @@ use profile::{memory_usage, Bytes};
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>()
-}
+use triomphe::Arc;
// Feature: Status
//
@@ -34,15 +37,22 @@ 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)));
+ format_to!(buf, "{} block def maps\n", collect_query_count(BlockDefMapQuery.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 +62,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 +78,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 +166,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<str>> for FilesStats {
+ fn collect_entry(&mut self, _: FileId, value: Option<Arc<str>>) {
+ 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<Option<(Parse<SyntaxNode>, M)>>>>
- for SyntaxTreeStats
-{
- fn from_iter<T>(iter: T) -> SyntaxTreeStats
- where
- T: IntoIterator<Item = TableEntry<MacroFile, ExpandResult<Option<(Parse<SyntaxNode>, M)>>>>,
- {
- let mut res = SyntaxTreeStats::default();
- for entry in iter {
- res.total += 1;
- res.retained += entry.value.is_some() as usize;
+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;
+ }
+}
+
+struct SymbolsStats<Key> {
+ total: usize,
+ size: Bytes,
+ phantom: PhantomData<Key>,
+}
+
+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 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>>) {
+ if let Some(symbols) = value {
+ self.total += symbols.len();
+ self.size += symbols.memory_size();
}
- res
}
}
#[derive(Default)]
-struct LibrarySymbolsStats {
+struct AttrsStats {
+ entries: usize,
total: usize,
- size: Bytes,
}
-impl fmt::Display for LibrarySymbolsStats {
+impl fmt::Display for AttrsStats {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(fmt, "{} of index symbols ({})", self.size, self.total)
+ 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 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
+impl<Key> StatCollect<Key, Attrs> for AttrsStats {
+ fn collect_entry(&mut self, _: Key, value: Option<Attrs>) {
+ self.entries += 1;
+ self.total += value.map_or(0, |it| it.len());
}
}