]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_query_impl/src/stats.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.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: map.iter_results(|results| results.count()),
54 local_def_id_keys: None,
55 };
56 map.iter_results(|results| {
57 for (key, _, _) in results {
58 key.key_stats(&mut stats)
59 }
60 });
61 stats
62 }
63
64 pub fn print_stats(tcx: TyCtxt<'_>) {
65 let queries = query_stats(tcx);
66
67 if cfg!(debug_assertions) {
68 let hits: usize = queries.iter().map(|s| s.cache_hits).sum();
69 let results: usize = queries.iter().map(|s| s.entry_count).sum();
70 eprintln!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64);
71 }
72
73 let mut query_key_sizes = queries.clone();
74 query_key_sizes.sort_by_key(|q| q.key_size);
75 eprintln!("\nLarge query keys:");
76 for q in query_key_sizes.iter().rev().filter(|q| q.key_size > 8) {
77 eprintln!(" {} - {} x {} - {}", q.name, q.key_size, q.entry_count, q.key_type);
78 }
79
80 let mut query_value_sizes = queries.clone();
81 query_value_sizes.sort_by_key(|q| q.value_size);
82 eprintln!("\nLarge query values:");
83 for q in query_value_sizes.iter().rev().filter(|q| q.value_size > 8) {
84 eprintln!(" {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type);
85 }
86
87 if cfg!(debug_assertions) {
88 let mut query_cache_hits = queries.clone();
89 query_cache_hits.sort_by_key(|q| q.cache_hits);
90 eprintln!("\nQuery cache hits:");
91 for q in query_cache_hits.iter().rev() {
92 eprintln!(
93 " {} - {} ({}%)",
94 q.name,
95 q.cache_hits,
96 q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64
97 );
98 }
99 }
100
101 let mut query_value_count = queries.clone();
102 query_value_count.sort_by_key(|q| q.entry_count);
103 eprintln!("\nQuery value count:");
104 for q in query_value_count.iter().rev() {
105 eprintln!(" {} - {}", q.name, q.entry_count);
106 }
107
108 let mut def_id_density: Vec<_> =
109 queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect();
110 def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap());
111 eprintln!("\nLocal DefId density:");
112 let total = tcx.hir().definitions().def_index_count() as f64;
113 for q in def_id_density.iter().rev() {
114 let local = q.local_def_id_keys.unwrap();
115 eprintln!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total);
116 }
117 }
118
119 macro_rules! print_stats {
120 (<$tcx:tt>
121 $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,)*
122 ) => {
123 fn query_stats(tcx: TyCtxt<'_>) -> Vec<QueryStats> {
124 let mut queries = Vec::new();
125
126 $(
127 queries.push(stats::<
128 query_storage::$name<'_>,
129 >(
130 stringify!($name),
131 &tcx.query_caches.$name,
132 ));
133 )*
134
135 queries
136 }
137 }
138 }
139
140 rustc_query_append! { [print_stats!][<'tcx>] }