aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/status.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/status.rs')
-rw-r--r--crates/ide/src/status.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
new file mode 100644
index 000000000..c23708181
--- /dev/null
+++ b/crates/ide/src/status.rs
@@ -0,0 +1,145 @@
1use std::{fmt, iter::FromIterator, sync::Arc};
2
3use base_db::{
4 salsa::debug::{DebugQueryTable, TableEntry},
5 FileTextQuery, SourceRootId,
6};
7use hir::MacroFile;
8use ide_db::{
9 symbol_index::{LibrarySymbolsQuery, SymbolIndex},
10 RootDatabase,
11};
12use profile::{memory_usage, Bytes};
13use rustc_hash::FxHashMap;
14use syntax::{ast, Parse, SyntaxNode};
15
16use crate::FileId;
17
18fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
19 base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>()
20}
21fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
22 hir::db::ParseMacroQuery.in_db(db).entries::<SyntaxTreeStats>()
23}
24
25// Feature: Status
26//
27// Shows internal statistic about memory usage of rust-analyzer.
28//
29// |===
30// | Editor | Action Name
31//
32// | VS Code | **Rust Analyzer: Status**
33// |===
34pub(crate) fn status(db: &RootDatabase) -> String {
35 let files_stats = FileTextQuery.in_db(db).entries::<FilesStats>();
36 let syntax_tree_stats = syntax_tree_stats(db);
37 let macro_syntax_tree_stats = macro_syntax_tree_stats(db);
38 let symbols_stats = LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>();
39 format!(
40 "{}\n{}\n{}\n{} (macros)\n\n\nmemory:\n{}\ngc {:?} seconds ago",
41 files_stats,
42 symbols_stats,
43 syntax_tree_stats,
44 macro_syntax_tree_stats,
45 memory_usage(),
46 db.last_gc.elapsed().as_secs(),
47 )
48}
49
50#[derive(Default)]
51struct FilesStats {
52 total: usize,
53 size: Bytes,
54}
55
56impl fmt::Display for FilesStats {
57 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
58 write!(fmt, "{} ({}) files", self.total, self.size)
59 }
60}
61
62impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats {
63 fn from_iter<T>(iter: T) -> FilesStats
64 where
65 T: IntoIterator<Item = TableEntry<FileId, Arc<String>>>,
66 {
67 let mut res = FilesStats::default();
68 for entry in iter {
69 res.total += 1;
70 res.size += entry.value.unwrap().len();
71 }
72 res
73 }
74}
75
76#[derive(Default)]
77pub(crate) struct SyntaxTreeStats {
78 total: usize,
79 pub(crate) retained: usize,
80}
81
82impl fmt::Display for SyntaxTreeStats {
83 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
84 write!(fmt, "{} trees, {} retained", self.total, self.retained)
85 }
86}
87
88impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStats {
89 fn from_iter<T>(iter: T) -> SyntaxTreeStats
90 where
91 T: IntoIterator<Item = TableEntry<FileId, Parse<ast::SourceFile>>>,
92 {
93 let mut res = SyntaxTreeStats::default();
94 for entry in iter {
95 res.total += 1;
96 res.retained += entry.value.is_some() as usize;
97 }
98 res
99 }
100}
101
102impl<M> FromIterator<TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>> for SyntaxTreeStats {
103 fn from_iter<T>(iter: T) -> SyntaxTreeStats
104 where
105 T: IntoIterator<Item = TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>>,
106 {
107 let mut res = SyntaxTreeStats::default();
108 for entry in iter {
109 res.total += 1;
110 res.retained += entry.value.is_some() as usize;
111 }
112 res
113 }
114}
115
116#[derive(Default)]
117struct LibrarySymbolsStats {
118 total: usize,
119 size: Bytes,
120}
121
122impl fmt::Display for LibrarySymbolsStats {
123 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
124 write!(fmt, "{} ({}) symbols", self.total, self.size)
125 }
126}
127
128impl FromIterator<TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>
129 for LibrarySymbolsStats
130{
131 fn from_iter<T>(iter: T) -> LibrarySymbolsStats
132 where
133 T: IntoIterator<Item = TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>,
134 {
135 let mut res = LibrarySymbolsStats::default();
136 for entry in iter {
137 let value = entry.value.unwrap();
138 for symbols in value.values() {
139 res.total += symbols.len();
140 res.size += symbols.memory_size();
141 }
142 }
143 res
144 }
145}