about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-04-22 09:34:47 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-04-22 09:34:47 +0200
commit63e3bf118d69f128f17508da9065b436be6da3c2 (patch)
tree6d222d92c48662bbb89b93f5a8934a5a29e88142
parente7285507f64c1b63e83cb38a2d005fdab5ff7387 (diff)
downloadrust-63e3bf118d69f128f17508da9065b436be6da3c2.tar.gz
rust-63e3bf118d69f128f17508da9065b436be6da3c2.zip
internal: Add some additional status ouput
-rw-r--r--crates/ide/src/status.rs241
-rw-r--r--crates/profile/src/memory_usage.rs6
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
     }