]>
git.proxmox.com Git - rustc.git/blob - src/librustc_passes/hir_stats.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // The visitors in this module collect sizes and counts of the most important
12 // pieces of AST and HIR. The resulting numbers are good approximations but not
13 // completely accurate (some things might be counted twice, others missed).
16 use rustc
::hir
::intravisit
as hir_visit
;
17 use rustc
::util
::common
::to_readable_str
;
18 use rustc
::util
::nodemap
::{FxHashMap, FxHashSet}
;
19 use syntax
::ast
::{self, NodeId, AttrId}
;
20 use syntax
::visit
as ast_visit
;
23 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
35 struct StatCollector
<'k
> {
36 krate
: Option
<&'k hir
::Crate
>,
37 data
: FxHashMap
<&'
static str, NodeData
>,
41 pub fn print_hir_stats(krate
: &hir
::Crate
) {
42 let mut collector
= StatCollector
{
47 hir_visit
::walk_crate(&mut collector
, krate
);
48 collector
.print("HIR STATS");
51 pub fn print_ast_stats
<'v
>(krate
: &'v ast
::Crate
, title
: &str) {
52 let mut collector
= StatCollector
{
57 ast_visit
::walk_crate(&mut collector
, krate
);
58 collector
.print(title
);
61 impl<'k
> StatCollector
<'k
> {
63 fn record
<T
>(&mut self, label
: &'
static str, id
: Id
, node
: &T
) {
65 if !self.seen
.insert(id
) {
70 let entry
= self.data
.entry(label
).or_insert(NodeData
{
76 entry
.size
= ::std
::mem
::size_of_val(node
);
79 fn print(&self, title
: &str) {
80 let mut stats
: Vec
<_
> = self.data
.iter().collect();
82 stats
.sort_by_key(|&(_
, ref d
)| d
.count
* d
.size
);
84 let mut total_size
= 0;
86 println
!("\n{}\n", title
);
88 println
!("{:<18}{:>18}{:>14}{:>14}",
89 "Name", "Accumulated Size", "Count", "Item Size");
90 println
!("----------------------------------------------------------------");
92 for (label
, data
) in stats
{
93 println
!("{:<18}{:>18}{:>14}{:>14}",
95 to_readable_str(data
.count
* data
.size
),
96 to_readable_str(data
.count
),
97 to_readable_str(data
.size
));
99 total_size
+= data
.count
* data
.size
;
101 println
!("----------------------------------------------------------------");
102 println
!("{:<18}{:>18}\n",
104 to_readable_str(total_size
));
108 impl<'v
> hir_visit
::Visitor
<'v
> for StatCollector
<'v
> {
109 fn nested_visit_map
<'this
>(&'this
mut self) -> hir_visit
::NestedVisitorMap
<'this
, 'v
> {
110 panic
!("visit_nested_xxx must be manually implemented in this visitor")
113 fn visit_nested_item(&mut self, id
: hir
::ItemId
) {
114 let nested_item
= self.krate
.unwrap().item(id
.id
);
115 self.visit_item(nested_item
)
118 fn visit_nested_trait_item(&mut self, trait_item_id
: hir
::TraitItemId
) {
119 let nested_trait_item
= self.krate
.unwrap().trait_item(trait_item_id
);
120 self.visit_trait_item(nested_trait_item
)
123 fn visit_nested_impl_item(&mut self, impl_item_id
: hir
::ImplItemId
) {
124 let nested_impl_item
= self.krate
.unwrap().impl_item(impl_item_id
);
125 self.visit_impl_item(nested_impl_item
)
128 fn visit_nested_body(&mut self, body_id
: hir
::BodyId
) {
129 let nested_body
= self.krate
.unwrap().body(body_id
);
130 self.visit_body(nested_body
)
133 fn visit_item(&mut self, i
: &'v hir
::Item
) {
134 self.record("Item", Id
::Node(i
.id
), i
);
135 hir_visit
::walk_item(self, i
)
138 ///////////////////////////////////////////////////////////////////////////
140 fn visit_mod(&mut self, m
: &'v hir
::Mod
, _s
: Span
, n
: NodeId
) {
141 self.record("Mod", Id
::None
, m
);
142 hir_visit
::walk_mod(self, m
, n
)
144 fn visit_foreign_item(&mut self, i
: &'v hir
::ForeignItem
) {
145 self.record("ForeignItem", Id
::Node(i
.id
), i
);
146 hir_visit
::walk_foreign_item(self, i
)
148 fn visit_local(&mut self, l
: &'v hir
::Local
) {
149 self.record("Local", Id
::Node(l
.id
), l
);
150 hir_visit
::walk_local(self, l
)
152 fn visit_block(&mut self, b
: &'v hir
::Block
) {
153 self.record("Block", Id
::Node(b
.id
), b
);
154 hir_visit
::walk_block(self, b
)
156 fn visit_stmt(&mut self, s
: &'v hir
::Stmt
) {
157 self.record("Stmt", Id
::Node(s
.node
.id()), s
);
158 hir_visit
::walk_stmt(self, s
)
160 fn visit_arm(&mut self, a
: &'v hir
::Arm
) {
161 self.record("Arm", Id
::None
, a
);
162 hir_visit
::walk_arm(self, a
)
164 fn visit_pat(&mut self, p
: &'v hir
::Pat
) {
165 self.record("Pat", Id
::Node(p
.id
), p
);
166 hir_visit
::walk_pat(self, p
)
168 fn visit_decl(&mut self, d
: &'v hir
::Decl
) {
169 self.record("Decl", Id
::None
, d
);
170 hir_visit
::walk_decl(self, d
)
172 fn visit_expr(&mut self, ex
: &'v hir
::Expr
) {
173 self.record("Expr", Id
::Node(ex
.id
), ex
);
174 hir_visit
::walk_expr(self, ex
)
177 fn visit_ty(&mut self, t
: &'v hir
::Ty
) {
178 self.record("Ty", Id
::Node(t
.id
), t
);
179 hir_visit
::walk_ty(self, t
)
182 fn visit_fn(&mut self,
183 fk
: hir_visit
::FnKind
<'v
>,
188 self.record("FnDecl", Id
::None
, fd
);
189 hir_visit
::walk_fn(self, fk
, fd
, b
, s
, id
)
192 fn visit_where_predicate(&mut self, predicate
: &'v hir
::WherePredicate
) {
193 self.record("WherePredicate", Id
::None
, predicate
);
194 hir_visit
::walk_where_predicate(self, predicate
)
197 fn visit_trait_item(&mut self, ti
: &'v hir
::TraitItem
) {
198 self.record("TraitItem", Id
::Node(ti
.id
), ti
);
199 hir_visit
::walk_trait_item(self, ti
)
201 fn visit_impl_item(&mut self, ii
: &'v hir
::ImplItem
) {
202 self.record("ImplItem", Id
::Node(ii
.id
), ii
);
203 hir_visit
::walk_impl_item(self, ii
)
206 fn visit_param_bound(&mut self, bounds
: &'v hir
::GenericBound
) {
207 self.record("GenericBound", Id
::None
, bounds
);
208 hir_visit
::walk_param_bound(self, bounds
)
211 fn visit_struct_field(&mut self, s
: &'v hir
::StructField
) {
212 self.record("StructField", Id
::Node(s
.id
), s
);
213 hir_visit
::walk_struct_field(self, s
)
216 fn visit_variant(&mut self,
218 g
: &'v hir
::Generics
,
220 self.record("Variant", Id
::None
, v
);
221 hir_visit
::walk_variant(self, v
, g
, item_id
)
223 fn visit_lifetime(&mut self, lifetime
: &'v hir
::Lifetime
) {
224 self.record("Lifetime", Id
::Node(lifetime
.id
), lifetime
);
225 hir_visit
::walk_lifetime(self, lifetime
)
227 fn visit_qpath(&mut self, qpath
: &'v hir
::QPath
, id
: NodeId
, span
: Span
) {
228 self.record("QPath", Id
::None
, qpath
);
229 hir_visit
::walk_qpath(self, qpath
, id
, span
)
231 fn visit_path(&mut self, path
: &'v hir
::Path
, _id
: NodeId
) {
232 self.record("Path", Id
::None
, path
);
233 hir_visit
::walk_path(self, path
)
235 fn visit_path_segment(&mut self,
237 path_segment
: &'v hir
::PathSegment
) {
238 self.record("PathSegment", Id
::None
, path_segment
);
239 hir_visit
::walk_path_segment(self, path_span
, path_segment
)
241 fn visit_assoc_type_binding(&mut self, type_binding
: &'v hir
::TypeBinding
) {
242 self.record("TypeBinding", Id
::Node(type_binding
.id
), type_binding
);
243 hir_visit
::walk_assoc_type_binding(self, type_binding
)
245 fn visit_attribute(&mut self, attr
: &'v ast
::Attribute
) {
246 self.record("Attribute", Id
::Attr(attr
.id
), attr
);
248 fn visit_macro_def(&mut self, macro_def
: &'v hir
::MacroDef
) {
249 self.record("MacroDef", Id
::Node(macro_def
.id
), macro_def
);
250 hir_visit
::walk_macro_def(self, macro_def
)
254 impl<'v
> ast_visit
::Visitor
<'v
> for StatCollector
<'v
> {
256 fn visit_mod(&mut self, m
: &'v ast
::Mod
, _s
: Span
, _a
: &[ast
::Attribute
], _n
: NodeId
) {
257 self.record("Mod", Id
::None
, m
);
258 ast_visit
::walk_mod(self, m
)
261 fn visit_foreign_item(&mut self, i
: &'v ast
::ForeignItem
) {
262 self.record("ForeignItem", Id
::None
, i
);
263 ast_visit
::walk_foreign_item(self, i
)
266 fn visit_item(&mut self, i
: &'v ast
::Item
) {
267 self.record("Item", Id
::None
, i
);
268 ast_visit
::walk_item(self, i
)
271 fn visit_local(&mut self, l
: &'v ast
::Local
) {
272 self.record("Local", Id
::None
, l
);
273 ast_visit
::walk_local(self, l
)
276 fn visit_block(&mut self, b
: &'v ast
::Block
) {
277 self.record("Block", Id
::None
, b
);
278 ast_visit
::walk_block(self, b
)
281 fn visit_stmt(&mut self, s
: &'v ast
::Stmt
) {
282 self.record("Stmt", Id
::None
, s
);
283 ast_visit
::walk_stmt(self, s
)
286 fn visit_arm(&mut self, a
: &'v ast
::Arm
) {
287 self.record("Arm", Id
::None
, a
);
288 ast_visit
::walk_arm(self, a
)
291 fn visit_pat(&mut self, p
: &'v ast
::Pat
) {
292 self.record("Pat", Id
::None
, p
);
293 ast_visit
::walk_pat(self, p
)
296 fn visit_expr(&mut self, ex
: &'v ast
::Expr
) {
297 self.record("Expr", Id
::None
, ex
);
298 ast_visit
::walk_expr(self, ex
)
301 fn visit_ty(&mut self, t
: &'v ast
::Ty
) {
302 self.record("Ty", Id
::None
, t
);
303 ast_visit
::walk_ty(self, t
)
306 fn visit_fn(&mut self,
307 fk
: ast_visit
::FnKind
<'v
>,
311 self.record("FnDecl", Id
::None
, fd
);
312 ast_visit
::walk_fn(self, fk
, fd
, s
)
315 fn visit_trait_item(&mut self, ti
: &'v ast
::TraitItem
) {
316 self.record("TraitItem", Id
::None
, ti
);
317 ast_visit
::walk_trait_item(self, ti
)
320 fn visit_impl_item(&mut self, ii
: &'v ast
::ImplItem
) {
321 self.record("ImplItem", Id
::None
, ii
);
322 ast_visit
::walk_impl_item(self, ii
)
325 fn visit_param_bound(&mut self, bounds
: &'v ast
::GenericBound
) {
326 self.record("GenericBound", Id
::None
, bounds
);
327 ast_visit
::walk_param_bound(self, bounds
)
330 fn visit_struct_field(&mut self, s
: &'v ast
::StructField
) {
331 self.record("StructField", Id
::None
, s
);
332 ast_visit
::walk_struct_field(self, s
)
335 fn visit_variant(&mut self,
337 g
: &'v ast
::Generics
,
339 self.record("Variant", Id
::None
, v
);
340 ast_visit
::walk_variant(self, v
, g
, item_id
)
343 fn visit_lifetime(&mut self, lifetime
: &'v ast
::Lifetime
) {
344 self.record("Lifetime", Id
::None
, lifetime
);
345 ast_visit
::walk_lifetime(self, lifetime
)
348 fn visit_mac(&mut self, mac
: &'v ast
::Mac
) {
349 self.record("Mac", Id
::None
, mac
);
352 fn visit_path_segment(&mut self,
354 path_segment
: &'v ast
::PathSegment
) {
355 self.record("PathSegment", Id
::None
, path_segment
);
356 ast_visit
::walk_path_segment(self, path_span
, path_segment
)
359 fn visit_assoc_type_binding(&mut self, type_binding
: &'v ast
::TypeBinding
) {
360 self.record("TypeBinding", Id
::None
, type_binding
);
361 ast_visit
::walk_assoc_type_binding(self, type_binding
)
364 fn visit_attribute(&mut self, attr
: &'v ast
::Attribute
) {
365 self.record("Attribute", Id
::None
, attr
);