]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_query_impl/src/stats.rs
Auto merge of #87019 - nikic:clang-12.0.1, r=Mark-Simulacrum
[rust.git] / compiler / rustc_query_impl / src / stats.rs
1 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
2 use rustc_middle::ty::query::query_storage;
3 use rustc_middle::ty::TyCtxt;
4 use rustc_query_system::query::{QueryCache, QueryCacheStore};
5
6 use std::any::type_name;
7 use std::mem;
8 #[cfg(debug_assertions)]
9 use std::sync::atomic::Ordering;
10
11 trait KeyStats {
12     fn key_stats(&self, stats: &mut QueryStats);
13 }
14
15 impl<T> KeyStats for T {
16     default fn key_stats(&self, _: &mut QueryStats) {}
17 }
18
19 impl KeyStats for DefId {
20     fn key_stats(&self, stats: &mut QueryStats) {
21         if self.krate == LOCAL_CRATE {
22             stats.local_def_id_keys = Some(stats.local_def_id_keys.unwrap_or(0) + 1);
23         }
24     }
25 }
26
27 #[derive(Clone)]
28 struct QueryStats {
29     name: &'static str,
30     cache_hits: usize,
31     key_size: usize,
32     key_type: &'static str,
33     value_size: usize,
34     value_type: &'static str,
35     entry_count: usize,
36     local_def_id_keys: Option<usize>,
37 }
38
39 fn stats<C>(name: &'static str, map: &QueryCacheStore<C>) -> QueryStats
40 where
41     C: QueryCache,
42 {
43     let mut stats = QueryStats {
44         name,
45         #[cfg(debug_assertions)]
46         cache_hits: map.cache_hits.load(Ordering::Relaxed),
47         #[cfg(not(debug_assertions))]
48         cache_hits: 0,
49         key_size: mem::size_of::<C::Key>(),
50         key_type: type_name::<C::Key>(),
51         value_size: mem::size_of::<C::Value>(),
52         value_type: type_name::<C::Value>(),
53         entry_count: 0,
54         local_def_id_keys: None,
55     };
56     map.iter_results(&mut |key, _, _| {
57         stats.entry_count += 1;
58         key.key_stats(&mut stats)
59     });
60     stats
61 }
62
63 pub fn print_stats(tcx: TyCtxt<'_>) {
64     let queries = query_stats(tcx);
65
66     if cfg!(debug_assertions) {
67         let hits: usize = queries.iter().map(|s| s.cache_hits).sum();
68         let results: usize = queries.iter().map(|s| s.entry_count).sum();
69         eprintln!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64);
70     }
71
72     let mut query_key_sizes = queries.clone();
73     query_key_sizes.sort_by_key(|q| q.key_size);
74     eprintln!("\nLarge query keys:");
75     for q in query_key_sizes.iter().rev().filter(|q| q.key_size > 8) {
76         eprintln!("   {} - {} x {} - {}", q.name, q.key_size, q.entry_count, q.key_type);
77     }
78
79     let mut query_value_sizes = queries.clone();
80     query_value_sizes.sort_by_key(|q| q.value_size);
81     eprintln!("\nLarge query values:");
82     for q in query_value_sizes.iter().rev().filter(|q| q.value_size > 8) {
83         eprintln!("   {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type);
84     }
85
86     if cfg!(debug_assertions) {
87         let mut query_cache_hits = queries.clone();
88         query_cache_hits.sort_by_key(|q| q.cache_hits);
89         eprintln!("\nQuery cache hits:");
90         for q in query_cache_hits.iter().rev() {
91             eprintln!(
92                 "   {} - {} ({}%)",
93                 q.name,
94                 q.cache_hits,
95                 q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64
96             );
97         }
98     }
99
100     let mut query_value_count = queries.clone();
101     query_value_count.sort_by_key(|q| q.entry_count);
102     eprintln!("\nQuery value count:");
103     for q in query_value_count.iter().rev() {
104         eprintln!("   {} - {}", q.name, q.entry_count);
105     }
106
107     let mut def_id_density: Vec<_> =
108         queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect();
109     def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap());
110     eprintln!("\nLocal DefId density:");
111     let total = tcx.resolutions(()).definitions.def_index_count() as f64;
112     for q in def_id_density.iter().rev() {
113         let local = q.local_def_id_keys.unwrap();
114         eprintln!("   {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total);
115     }
116 }
117
118 macro_rules! print_stats {
119     (<$tcx:tt>
120         $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,)*
121     ) => {
122         fn query_stats(tcx: TyCtxt<'_>) -> Vec<QueryStats> {
123             let mut queries = Vec::new();
124
125             $(
126                 queries.push(stats::<
127                     query_storage::$name<'_>,
128                 >(
129                     stringify!($name),
130                     &tcx.query_caches.$name,
131                 ));
132             )*
133
134             queries
135         }
136     }
137 }
138
139 rustc_query_append! { [print_stats!][<'tcx>] }