1 use std
::{fmt, iter::FromIterator, sync::Arc}
;
3 use hir
::{ExpandResult, MacroFile}
;
5 salsa
::debug
::{DebugQueryTable, TableEntry}
,
6 CrateId
, FileId
, FileTextQuery
, SourceDatabase
, SourceRootId
,
9 symbol_index
::{LibrarySymbolsQuery, SymbolIndex}
,
12 use itertools
::Itertools
;
13 use profile
::{memory_usage, Bytes}
;
16 use syntax
::{ast, Parse, SyntaxNode}
;
18 fn syntax_tree_stats(db
: &RootDatabase
) -> SyntaxTreeStats
{
19 ide_db
::base_db
::ParseQuery
.in_db(db
).entries
::<SyntaxTreeStats
>()
21 fn macro_syntax_tree_stats(db
: &RootDatabase
) -> SyntaxTreeStats
{
22 hir
::db
::ParseMacroExpansionQuery
.in_db(db
).entries
::<SyntaxTreeStats
>()
27 // Shows internal statistic about memory usage of rust-analyzer.
30 // | Editor | Action Name
32 // | VS Code | **Rust Analyzer: Status**
34 // image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
35 pub(crate) fn status(db
: &RootDatabase
, file_id
: Option
<FileId
>) -> String
{
36 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
));
41 format_to
!(buf
, "{} in total\n", memory_usage());
42 if env
::var("RA_COUNT").is_ok() {
43 format_to
!(buf
, "\nCounts:\n{}", profile
::countme
::get_all());
46 if let Some(file_id
) = file_id
{
47 format_to
!(buf
, "\nFile info:\n");
48 let crates
= crate::parent_module
::crate_for(db
, file_id
);
49 if crates
.is_empty() {
50 format_to
!(buf
, "Does not belong to any crate");
52 let crate_graph
= db
.crate_graph();
54 let display_crate
= |krate
: CrateId
| match &crate_graph
[krate
].display_name
{
55 Some(it
) => format
!("{}({:?})", it
, krate
),
56 None
=> format
!("{:?}", krate
),
58 format_to
!(buf
, "Crate: {}\n", display_crate(krate
));
59 let deps
= crate_graph
[krate
]
62 .map(|dep
| format
!("{}={:?}", dep
.name
, dep
.crate_id
))
64 format_to
!(buf
, "Dependencies: {}\n", deps
);
68 buf
.trim().to_string()
77 impl fmt
::Display
for FilesStats
{
78 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
79 write
!(fmt
, "{} of files", self.size
)
83 impl FromIterator
<TableEntry
<FileId
, Arc
<String
>>> for FilesStats
{
84 fn from_iter
<T
>(iter
: T
) -> FilesStats
86 T
: IntoIterator
<Item
= TableEntry
<FileId
, Arc
<String
>>>,
88 let mut res
= FilesStats
::default();
91 res
.size
+= entry
.value
.unwrap().len();
98 pub(crate) struct SyntaxTreeStats
{
100 pub(crate) retained
: usize,
103 impl fmt
::Display
for SyntaxTreeStats
{
104 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
105 write
!(fmt
, "{} trees, {} preserved", self.total
, self.retained
)
109 impl FromIterator
<TableEntry
<FileId
, Parse
<ast
::SourceFile
>>> for SyntaxTreeStats
{
110 fn from_iter
<T
>(iter
: T
) -> SyntaxTreeStats
112 T
: IntoIterator
<Item
= TableEntry
<FileId
, Parse
<ast
::SourceFile
>>>,
114 let mut res
= SyntaxTreeStats
::default();
117 res
.retained
+= entry
.value
.is_some() as usize;
123 impl<M
> FromIterator
<TableEntry
<MacroFile
, ExpandResult
<Option
<(Parse
<SyntaxNode
>, M
)>>>>
126 fn from_iter
<T
>(iter
: T
) -> SyntaxTreeStats
128 T
: IntoIterator
<Item
= TableEntry
<MacroFile
, ExpandResult
<Option
<(Parse
<SyntaxNode
>, M
)>>>>,
130 let mut res
= SyntaxTreeStats
::default();
133 res
.retained
+= entry
.value
.is_some() as usize;
140 struct LibrarySymbolsStats
{
145 impl fmt
::Display
for LibrarySymbolsStats
{
146 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
147 write
!(fmt
, "{} of index symbols ({})", self.size
, self.total
)
151 impl FromIterator
<TableEntry
<SourceRootId
, Arc
<SymbolIndex
>>> for LibrarySymbolsStats
{
152 fn from_iter
<T
>(iter
: T
) -> LibrarySymbolsStats
154 T
: IntoIterator
<Item
= TableEntry
<SourceRootId
, Arc
<SymbolIndex
>>>,
156 let mut res
= LibrarySymbolsStats
::default();
158 let symbols
= entry
.value
.unwrap();
159 res
.total
+= symbols
.len();
160 res
.size
+= symbols
.memory_size();