1- use std:: { fmt, sync:: Arc } ;
1+ use std:: { fmt, marker :: PhantomData , sync:: Arc } ;
22
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 ,
716} ;
817use ide_db:: {
918 symbol_index:: { LibrarySymbolsQuery , SymbolIndex } ,
@@ -15,13 +24,6 @@ use std::env;
1524use stdx:: format_to;
1625use syntax:: { ast, Parse , SyntaxNode } ;
1726
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-
2527// Feature: Status
2628//
2729// Shows internal statistic about memory usage of rust-analyzer.
@@ -34,15 +36,21 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
3436// image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
3537pub ( crate ) fn status ( db : & RootDatabase , file_id : Option < FileId > ) -> String {
3638 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) ) ) ;
4145 format_to ! ( buf, "{} in total\n " , memory_usage( ) ) ;
4246 if env:: var ( "RA_COUNT" ) . is_ok ( ) {
4347 format_to ! ( buf, "\n Counts:\n {}" , profile:: countme:: get_all( ) ) ;
4448 }
4549
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+
4654 if let Some ( file_id) = file_id {
4755 format_to ! ( buf, "\n File info:\n " ) ;
4856 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 {
5260 let crate_graph = db. crate_graph ( ) ;
5361 for krate in crates {
5462 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 ( ) ) ,
5765 } ;
5866 format_to ! ( buf, "Crate: {}\n " , display_crate( krate) ) ;
5967 let deps = crate_graph[ krate]
@@ -68,6 +76,82 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
6876 buf. trim ( ) . to_string ( )
6977}
7078
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+
71155#[ derive( Default ) ]
72156struct FilesStats {
73157 total : usize ,
@@ -80,85 +164,98 @@ impl fmt::Display for FilesStats {
80164 }
81165}
82166
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 ( ) ;
94171 }
95172}
96173
97174#[ derive( Default ) ]
98- pub ( crate ) struct SyntaxTreeStats {
175+ pub ( crate ) struct SyntaxTreeStats < const MACROS : bool > {
99176 total : usize ,
100177 pub ( crate ) retained : usize ,
101178}
102179
103- impl fmt:: Display for SyntaxTreeStats {
180+ impl < const MACROS : bool > fmt:: Display for SyntaxTreeStats < MACROS > {
104181 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+ )
106189 }
107190}
108191
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 ;
120196 }
121197}
122198
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 ;
136203 }
137204}
138205
139- #[ derive( Default ) ]
140- struct LibrarySymbolsStats {
206+ struct SymbolsStats < Key > {
141207 total : usize ,
142208 size : Bytes ,
209+ phantom : PhantomData < Key > ,
143210}
144211
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 > {
146219 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 ( ) ;
148233 }
149234}
150235
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 ( ) ;
163260 }
164261}
0 commit comments