1
- use std:: { fmt, sync:: Arc } ;
1
+ use std:: { fmt, marker :: PhantomData , sync:: Arc } ;
2
2
3
- use hir:: { ExpandResult , MacroFile } ;
4
- use ide_db:: base_db:: {
5
- salsa:: debug:: { DebugQueryTable , TableEntry } ,
6
- CrateId , FileId , FileTextQuery , SourceDatabase , SourceRootId ,
3
+ use hir:: {
4
+ db:: { AstIdMapQuery , AttrsQuery , ParseMacroExpansionQuery } ,
5
+ Attr , Attrs , ExpandResult , MacroFile , Module ,
6
+ } ;
7
+ use ide_db:: {
8
+ base_db:: {
9
+ salsa:: {
10
+ debug:: { DebugQueryTable , TableEntry } ,
11
+ Query , QueryTable ,
12
+ } ,
13
+ CrateId , FileId , FileTextQuery , ParseQuery , SourceDatabase , SourceRootId ,
14
+ } ,
15
+ symbol_index:: ModuleSymbolsQuery ,
7
16
} ;
8
17
use ide_db:: {
9
18
symbol_index:: { LibrarySymbolsQuery , SymbolIndex } ,
@@ -15,13 +24,6 @@ use std::env;
15
24
use stdx:: format_to;
16
25
use syntax:: { ast, Parse , SyntaxNode } ;
17
26
18
- fn syntax_tree_stats ( db : & RootDatabase ) -> SyntaxTreeStats {
19
- ide_db:: base_db:: ParseQuery . in_db ( db) . entries :: < SyntaxTreeStats > ( )
20
- }
21
- fn macro_syntax_tree_stats ( db : & RootDatabase ) -> SyntaxTreeStats {
22
- hir:: db:: ParseMacroExpansionQuery . in_db ( db) . entries :: < SyntaxTreeStats > ( )
23
- }
24
-
25
27
// Feature: Status
26
28
//
27
29
// Shows internal statistic about memory usage of rust-analyzer.
@@ -34,15 +36,21 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
34
36
// image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
35
37
pub ( crate ) fn status ( db : & RootDatabase , file_id : Option < FileId > ) -> String {
36
38
let mut buf = String :: new ( ) ;
37
- format_to ! ( buf, "{}\n " , FileTextQuery . in_db( db) . entries:: <FilesStats >( ) ) ;
38
- format_to ! ( buf, "{}\n " , LibrarySymbolsQuery . in_db( db) . entries:: <LibrarySymbolsStats >( ) ) ;
39
- format_to ! ( buf, "{}\n " , syntax_tree_stats( db) ) ;
40
- format_to ! ( buf, "{} (Macros)\n " , macro_syntax_tree_stats( db) ) ;
39
+
40
+ format_to ! ( buf, "{}\n " , collect_query( FileTextQuery . in_db( db) ) ) ;
41
+ format_to ! ( buf, "{}\n " , collect_query( ParseQuery . in_db( db) ) ) ;
42
+ format_to ! ( buf, "{}\n " , collect_query( ParseMacroExpansionQuery . in_db( db) ) ) ;
43
+ format_to ! ( buf, "{}\n " , collect_query( LibrarySymbolsQuery . in_db( db) ) ) ;
44
+ format_to ! ( buf, "{}\n " , collect_query( ModuleSymbolsQuery . in_db( db) ) ) ;
41
45
format_to ! ( buf, "{} in total\n " , memory_usage( ) ) ;
42
46
if env:: var ( "RA_COUNT" ) . is_ok ( ) {
43
47
format_to ! ( buf, "\n Counts:\n {}" , profile:: countme:: get_all( ) ) ;
44
48
}
45
49
50
+ format_to ! ( buf, "\n Debug info:\n " ) ;
51
+ format_to ! ( buf, "{}\n " , collect_query( AttrsQuery . in_db( db) ) ) ;
52
+ format_to ! ( buf, "{} ast id maps\n " , collect_query_count( AstIdMapQuery . in_db( db) ) ) ;
53
+
46
54
if let Some ( file_id) = file_id {
47
55
format_to ! ( buf, "\n File info:\n " ) ;
48
56
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 {
52
60
let crate_graph = db. crate_graph ( ) ;
53
61
for krate in crates {
54
62
let display_crate = |krate : CrateId | match & crate_graph[ krate] . display_name {
55
- Some ( it) => format ! ( "{it}({krate:? })" ) ,
56
- None => format ! ( "{krate:?}" ) ,
63
+ Some ( it) => format ! ( "{it}({})" , krate . into_raw ( ) ) ,
64
+ None => format ! ( "{}" , krate . into_raw ( ) ) ,
57
65
} ;
58
66
format_to ! ( buf, "Crate: {}\n " , display_crate( krate) ) ;
59
67
let deps = crate_graph[ krate]
@@ -68,6 +76,82 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
68
76
buf. trim ( ) . to_string ( )
69
77
}
70
78
79
+ fn collect_query < ' q , Q > ( table : QueryTable < ' q , Q > ) -> <Q as QueryCollect >:: Collector
80
+ where
81
+ QueryTable < ' q , Q > : DebugQueryTable ,
82
+ Q : QueryCollect ,
83
+ <Q as Query >:: Storage : ' q ,
84
+ <Q as QueryCollect >:: Collector : StatCollect <
85
+ <QueryTable < ' q , Q > as DebugQueryTable >:: Key ,
86
+ <QueryTable < ' q , Q > as DebugQueryTable >:: Value ,
87
+ > ,
88
+ {
89
+ struct StatCollectorWrapper < C > ( C ) ;
90
+ impl < C : StatCollect < K , V > , K , V > FromIterator < TableEntry < K , V > > for StatCollectorWrapper < C > {
91
+ fn from_iter < T > ( iter : T ) -> StatCollectorWrapper < C >
92
+ where
93
+ T : IntoIterator < Item = TableEntry < K , V > > ,
94
+ {
95
+ let mut res = C :: default ( ) ;
96
+ for entry in iter {
97
+ res. collect_entry ( entry. key , entry. value ) ;
98
+ }
99
+ StatCollectorWrapper ( res)
100
+ }
101
+ }
102
+ table. entries :: < StatCollectorWrapper < <Q as QueryCollect >:: Collector > > ( ) . 0
103
+ }
104
+
105
+ fn collect_query_count < ' q , Q > ( table : QueryTable < ' q , Q > ) -> usize
106
+ where
107
+ QueryTable < ' q , Q > : DebugQueryTable ,
108
+ Q : Query ,
109
+ <Q as Query >:: Storage : ' q ,
110
+ {
111
+ struct EntryCounter ( usize ) ;
112
+ impl < K , V > FromIterator < TableEntry < K , V > > for EntryCounter {
113
+ fn from_iter < T > ( iter : T ) -> EntryCounter
114
+ where
115
+ T : IntoIterator < Item = TableEntry < K , V > > ,
116
+ {
117
+ EntryCounter ( iter. into_iter ( ) . count ( ) )
118
+ }
119
+ }
120
+ table. entries :: < EntryCounter > ( ) . 0
121
+ }
122
+
123
+ trait QueryCollect : Query {
124
+ type Collector ;
125
+ }
126
+
127
+ impl QueryCollect for LibrarySymbolsQuery {
128
+ type Collector = SymbolsStats < SourceRootId > ;
129
+ }
130
+
131
+ impl QueryCollect for ParseQuery {
132
+ type Collector = SyntaxTreeStats < false > ;
133
+ }
134
+
135
+ impl QueryCollect for ParseMacroExpansionQuery {
136
+ type Collector = SyntaxTreeStats < true > ;
137
+ }
138
+
139
+ impl QueryCollect for FileTextQuery {
140
+ type Collector = FilesStats ;
141
+ }
142
+
143
+ impl QueryCollect for ModuleSymbolsQuery {
144
+ type Collector = SymbolsStats < Module > ;
145
+ }
146
+
147
+ impl QueryCollect for AttrsQuery {
148
+ type Collector = AttrsStats ;
149
+ }
150
+
151
+ trait StatCollect < K , V > : Default {
152
+ fn collect_entry ( & mut self , key : K , value : Option < V > ) ;
153
+ }
154
+
71
155
#[ derive( Default ) ]
72
156
struct FilesStats {
73
157
total : usize ,
@@ -80,85 +164,98 @@ impl fmt::Display for FilesStats {
80
164
}
81
165
}
82
166
83
- impl FromIterator < TableEntry < FileId , Arc < String > > > for FilesStats {
84
- fn from_iter < T > ( iter : T ) -> FilesStats
85
- where
86
- T : IntoIterator < Item = TableEntry < FileId , Arc < String > > > ,
87
- {
88
- let mut res = FilesStats :: default ( ) ;
89
- for entry in iter {
90
- res. total += 1 ;
91
- res. size += entry. value . unwrap ( ) . len ( ) ;
92
- }
93
- res
167
+ impl StatCollect < FileId , Arc < String > > for FilesStats {
168
+ fn collect_entry ( & mut self , _: FileId , value : Option < Arc < String > > ) {
169
+ self . total += 1 ;
170
+ self . size += value. unwrap ( ) . len ( ) ;
94
171
}
95
172
}
96
173
97
174
#[ derive( Default ) ]
98
- pub ( crate ) struct SyntaxTreeStats {
175
+ pub ( crate ) struct SyntaxTreeStats < const MACROS : bool > {
99
176
total : usize ,
100
177
pub ( crate ) retained : usize ,
101
178
}
102
179
103
- impl fmt:: Display for SyntaxTreeStats {
180
+ impl < const MACROS : bool > fmt:: Display for SyntaxTreeStats < MACROS > {
104
181
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
105
- write ! ( fmt, "{} trees, {} preserved" , self . total, self . retained)
182
+ write ! (
183
+ fmt,
184
+ "{} trees, {} preserved{}" ,
185
+ self . total,
186
+ self . retained,
187
+ if MACROS { " (macros)" } else { "" }
188
+ )
106
189
}
107
190
}
108
191
109
- impl FromIterator < TableEntry < FileId , Parse < ast:: SourceFile > > > for SyntaxTreeStats {
110
- fn from_iter < T > ( iter : T ) -> SyntaxTreeStats
111
- where
112
- T : IntoIterator < Item = TableEntry < FileId , Parse < ast:: SourceFile > > > ,
113
- {
114
- let mut res = SyntaxTreeStats :: default ( ) ;
115
- for entry in iter {
116
- res. total += 1 ;
117
- res. retained += entry. value . is_some ( ) as usize ;
118
- }
119
- res
192
+ impl StatCollect < FileId , Parse < ast:: SourceFile > > for SyntaxTreeStats < false > {
193
+ fn collect_entry ( & mut self , _: FileId , value : Option < Parse < ast:: SourceFile > > ) {
194
+ self . total += 1 ;
195
+ self . retained += value. is_some ( ) as usize ;
120
196
}
121
197
}
122
198
123
- impl < M > FromIterator < TableEntry < MacroFile , ExpandResult < ( Parse < SyntaxNode > , M ) > > >
124
- for SyntaxTreeStats
125
- {
126
- fn from_iter < T > ( iter : T ) -> SyntaxTreeStats
127
- where
128
- T : IntoIterator < Item = TableEntry < MacroFile , ExpandResult < ( Parse < SyntaxNode > , M ) > > > ,
129
- {
130
- let mut res = SyntaxTreeStats :: default ( ) ;
131
- for entry in iter {
132
- res. total += 1 ;
133
- res. retained += entry. value . is_some ( ) as usize ;
134
- }
135
- res
199
+ impl < M > StatCollect < MacroFile , ExpandResult < ( Parse < SyntaxNode > , M ) > > for SyntaxTreeStats < true > {
200
+ fn collect_entry ( & mut self , _: MacroFile , value : Option < ExpandResult < ( Parse < SyntaxNode > , M ) > > ) {
201
+ self . total += 1 ;
202
+ self . retained += value. is_some ( ) as usize ;
136
203
}
137
204
}
138
205
139
- #[ derive( Default ) ]
140
- struct LibrarySymbolsStats {
206
+ struct SymbolsStats < Key > {
141
207
total : usize ,
142
208
size : Bytes ,
209
+ phantom : PhantomData < Key > ,
143
210
}
144
211
145
- impl fmt:: Display for LibrarySymbolsStats {
212
+ impl < Key > Default for SymbolsStats < Key > {
213
+ fn default ( ) -> Self {
214
+ Self { total : Default :: default ( ) , size : Default :: default ( ) , phantom : PhantomData }
215
+ }
216
+ }
217
+
218
+ impl fmt:: Display for SymbolsStats < Module > {
146
219
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
147
- write ! ( fmt, "{} of index symbols ({})" , self . size, self . total)
220
+ write ! ( fmt, "{} of module index symbols ({})" , self . size, self . total)
221
+ }
222
+ }
223
+ impl fmt:: Display for SymbolsStats < SourceRootId > {
224
+ fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
225
+ write ! ( fmt, "{} of library index symbols ({})" , self . size, self . total)
226
+ }
227
+ }
228
+ impl < Key > StatCollect < Key , Arc < SymbolIndex > > for SymbolsStats < Key > {
229
+ fn collect_entry ( & mut self , _: Key , value : Option < Arc < SymbolIndex > > ) {
230
+ let symbols = value. unwrap ( ) ;
231
+ self . total += symbols. len ( ) ;
232
+ self . size += symbols. memory_size ( ) ;
148
233
}
149
234
}
150
235
151
- impl FromIterator < TableEntry < SourceRootId , Arc < SymbolIndex > > > for LibrarySymbolsStats {
152
- fn from_iter < T > ( iter : T ) -> LibrarySymbolsStats
153
- where
154
- T : IntoIterator < Item = TableEntry < SourceRootId , Arc < SymbolIndex > > > ,
155
- {
156
- let mut res = LibrarySymbolsStats :: default ( ) ;
157
- for entry in iter {
158
- let symbols = entry. value . unwrap ( ) ;
159
- res. total += symbols. len ( ) ;
160
- res. size += symbols. memory_size ( ) ;
161
- }
162
- res
236
+ #[ derive( Default ) ]
237
+ struct AttrsStats {
238
+ entries : usize ,
239
+ total : usize ,
240
+ }
241
+
242
+ impl fmt:: Display for AttrsStats {
243
+ fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
244
+ let size =
245
+ self . entries * std:: mem:: size_of :: < Attrs > ( ) + self . total * std:: mem:: size_of :: < Attr > ( ) ;
246
+ let size = Bytes :: new ( size as _ ) ;
247
+ write ! (
248
+ fmt,
249
+ "{} attribute query entries, {} total attributes ({} for storing entries)" ,
250
+ self . entries, self . total, size
251
+ )
252
+ }
253
+ }
254
+
255
+ impl < Key > StatCollect < Key , Attrs > for AttrsStats {
256
+ fn collect_entry ( & mut self , _: Key , value : Option < Attrs > ) {
257
+ let attrs = value. unwrap ( ) ;
258
+ self . entries += 1 ;
259
+ self . total += attrs. len ( ) ;
163
260
}
164
261
}
0 commit comments