diff options
-rw-r--r-- | crates/ra_ide_api/src/status.rs | 154 | ||||
-rw-r--r-- | crates/ra_ide_api/src/symbol_index.rs | 9 |
2 files changed, 130 insertions, 33 deletions
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs index c184ca892..717537fcd 100644 --- a/crates/ra_ide_api/src/status.rs +++ b/crates/ra_ide_api/src/status.rs | |||
@@ -1,61 +1,149 @@ | |||
1 | use std::fmt; | 1 | use std::{ |
2 | fmt, | ||
3 | iter::FromIterator, | ||
4 | sync::Arc, | ||
5 | }; | ||
2 | 6 | ||
3 | use ra_syntax::AstNode; | 7 | use ra_syntax::{AstNode, TreeArc, SourceFile}; |
4 | use ra_db::{ | 8 | use ra_db::{ |
5 | SourceFileQuery, | 9 | SourceFileQuery, FileTextQuery, SourceRootId, |
6 | salsa::{Database, debug::DebugQueryTable}, | 10 | salsa::{Database, debug::{DebugQueryTable, TableEntry}}, |
7 | }; | 11 | }; |
8 | 12 | ||
9 | use crate::db::RootDatabase; | 13 | use crate::{ |
14 | FileId, db::RootDatabase, | ||
15 | symbol_index::{SymbolIndex, LibrarySymbolsQuery}, | ||
16 | }; | ||
10 | 17 | ||
11 | pub(crate) fn status(db: &RootDatabase) -> String { | 18 | pub(crate) fn status(db: &RootDatabase) -> String { |
12 | let file_stats = { | 19 | let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); |
13 | let mut stats = FilesStats::default(); | 20 | let syntax_tree_stats = db.query(SourceFileQuery).entries::<SyntaxTreeStats>(); |
14 | for entry in db.query(SourceFileQuery).entries::<Vec<_>>() { | 21 | let symbols_stats = db |
15 | stats.total += 1; | 22 | .query(LibrarySymbolsQuery) |
16 | if let Some(value) = entry.value { | 23 | .entries::<LibrarySymbolsStats>(); |
17 | stats.retained += 1; | ||
18 | stats.retained_size = stats | ||
19 | .retained_size | ||
20 | .checked_add(value.syntax().memory_size_of_subtree()) | ||
21 | .unwrap(); | ||
22 | } | ||
23 | } | ||
24 | stats | ||
25 | }; | ||
26 | let n_defs = { | 24 | let n_defs = { |
27 | let interner: &hir::HirInterner = db.as_ref(); | 25 | let interner: &hir::HirInterner = db.as_ref(); |
28 | interner.len() | 26 | interner.len() |
29 | }; | 27 | }; |
30 | format!("{}\nn_defs {}\n", file_stats, n_defs) | 28 | format!( |
29 | "{}\n{}\n{}\nn_defs {}\n", | ||
30 | files_stats, symbols_stats, syntax_tree_stats, n_defs | ||
31 | ) | ||
31 | } | 32 | } |
32 | 33 | ||
33 | #[derive(Default)] | 34 | #[derive(Default)] |
34 | struct FilesStats { | 35 | struct FilesStats { |
35 | total: usize, | 36 | total: usize, |
36 | retained: usize, | 37 | size: Bytes, |
37 | retained_size: usize, | ||
38 | } | 38 | } |
39 | 39 | ||
40 | impl fmt::Display for FilesStats { | 40 | impl fmt::Display for FilesStats { |
41 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 41 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
42 | let (size, suff) = human_bytes(self.retained_size); | 42 | write!(fmt, "{} ({}) files", self.total, self.size) |
43 | } | ||
44 | } | ||
45 | |||
46 | impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats { | ||
47 | fn from_iter<T>(iter: T) -> FilesStats | ||
48 | where | ||
49 | T: IntoIterator<Item = TableEntry<FileId, Arc<String>>>, | ||
50 | { | ||
51 | let mut res = FilesStats::default(); | ||
52 | for entry in iter { | ||
53 | res.total += 1; | ||
54 | res.size += entry.value.unwrap().len(); | ||
55 | } | ||
56 | res | ||
57 | } | ||
58 | } | ||
59 | |||
60 | #[derive(Default)] | ||
61 | struct SyntaxTreeStats { | ||
62 | total: usize, | ||
63 | retained: usize, | ||
64 | retained_size: Bytes, | ||
65 | } | ||
66 | |||
67 | impl fmt::Display for SyntaxTreeStats { | ||
68 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
43 | write!( | 69 | write!( |
44 | fmt, | 70 | fmt, |
45 | "{} parsed_files, {} ({}{}) retained", | 71 | "{} trees, {} ({}) retained", |
46 | self.total, self.retained, size, suff | 72 | self.total, self.retained, self.retained_size, |
47 | ) | 73 | ) |
48 | } | 74 | } |
49 | } | 75 | } |
50 | 76 | ||
51 | fn human_bytes(bytes: usize) -> (usize, &'static str) { | 77 | impl FromIterator<TableEntry<FileId, TreeArc<SourceFile>>> for SyntaxTreeStats { |
52 | if bytes < 4096 { | 78 | fn from_iter<T>(iter: T) -> SyntaxTreeStats |
53 | return (bytes, " bytes"); | 79 | where |
80 | T: IntoIterator<Item = TableEntry<FileId, TreeArc<SourceFile>>>, | ||
81 | { | ||
82 | let mut res = SyntaxTreeStats::default(); | ||
83 | for entry in iter { | ||
84 | res.total += 1; | ||
85 | if let Some(value) = entry.value { | ||
86 | res.retained += 1; | ||
87 | res.retained_size += value.syntax().memory_size_of_subtree(); | ||
88 | } | ||
89 | } | ||
90 | res | ||
54 | } | 91 | } |
55 | let kb = bytes / 1024; | 92 | } |
56 | if kb < 4096 { | 93 | |
57 | return (kb, "kb"); | 94 | #[derive(Default)] |
95 | struct LibrarySymbolsStats { | ||
96 | total: usize, | ||
97 | fst_size: Bytes, | ||
98 | symbols_size: Bytes, | ||
99 | } | ||
100 | |||
101 | impl fmt::Display for LibrarySymbolsStats { | ||
102 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
103 | write!( | ||
104 | fmt, | ||
105 | "{} ({} + {}) symbols", | ||
106 | self.total, self.fst_size, self.symbols_size | ||
107 | ) | ||
108 | } | ||
109 | } | ||
110 | |||
111 | impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbolsStats { | ||
112 | fn from_iter<T>(iter: T) -> LibrarySymbolsStats | ||
113 | where | ||
114 | T: IntoIterator<Item = TableEntry<SourceRootId, Arc<SymbolIndex>>>, | ||
115 | { | ||
116 | let mut res = LibrarySymbolsStats::default(); | ||
117 | for entry in iter { | ||
118 | let value = entry.value.unwrap(); | ||
119 | res.total += value.len(); | ||
120 | res.fst_size += value.fst_size(); | ||
121 | res.symbols_size += value.symbols_size(); | ||
122 | } | ||
123 | res | ||
124 | } | ||
125 | } | ||
126 | |||
127 | #[derive(Default)] | ||
128 | struct Bytes(usize); | ||
129 | |||
130 | impl fmt::Display for Bytes { | ||
131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
132 | let bytes = self.0; | ||
133 | if bytes < 4096 { | ||
134 | return write!(f, "{} bytes", bytes); | ||
135 | } | ||
136 | let kb = bytes / 1024; | ||
137 | if kb < 4096 { | ||
138 | return write!(f, "{}kb", kb); | ||
139 | } | ||
140 | let mb = kb / 1024; | ||
141 | write!(f, "{}mb", mb) | ||
142 | } | ||
143 | } | ||
144 | |||
145 | impl std::ops::AddAssign<usize> for Bytes { | ||
146 | fn add_assign(&mut self, x: usize) { | ||
147 | self.0 += x; | ||
58 | } | 148 | } |
59 | let mb = kb / 1024; | ||
60 | (mb, "mb") | ||
61 | } | 149 | } |
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs index 1b5d1eb1d..69a669b8d 100644 --- a/crates/ra_ide_api/src/symbol_index.rs +++ b/crates/ra_ide_api/src/symbol_index.rs | |||
@@ -23,6 +23,7 @@ use std::{ | |||
23 | cmp::Ordering, | 23 | cmp::Ordering, |
24 | hash::{Hash, Hasher}, | 24 | hash::{Hash, Hasher}, |
25 | sync::Arc, | 25 | sync::Arc, |
26 | mem, | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | use fst::{self, Streamer}; | 29 | use fst::{self, Streamer}; |
@@ -136,6 +137,14 @@ impl SymbolIndex { | |||
136 | self.symbols.len() | 137 | self.symbols.len() |
137 | } | 138 | } |
138 | 139 | ||
140 | pub(crate) fn fst_size(&self) -> usize { | ||
141 | self.map.as_fst().size() | ||
142 | } | ||
143 | |||
144 | pub(crate) fn symbols_size(&self) -> usize { | ||
145 | self.symbols.len() * mem::size_of::<FileSymbol>() | ||
146 | } | ||
147 | |||
139 | pub(crate) fn for_files( | 148 | pub(crate) fn for_files( |
140 | files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>, | 149 | files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>, |
141 | ) -> SymbolIndex { | 150 | ) -> SymbolIndex { |