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