]>
Commit | Line | Data |
---|---|---|
74b04a01 XL |
1 | use crate::ty::query::config::QueryAccessors; |
2 | use crate::ty::query::plumbing::QueryState; | |
3 | use crate::ty::query::queries; | |
4 | use crate::ty::TyCtxt; | |
5 | use rustc_hir::def_id::{DefId, LOCAL_CRATE}; | |
6 | ||
7 | use std::any::type_name; | |
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<'tcx, Q: QueryAccessors<'tcx>>( | |
41 | name: &'static str, | |
42 | map: &QueryState<'tcx, Q>, | |
43 | ) -> QueryStats { | |
44 | let mut stats = QueryStats { | |
45 | name, | |
46 | #[cfg(debug_assertions)] | |
47 | cache_hits: map.cache_hits.load(Ordering::Relaxed), | |
48 | #[cfg(not(debug_assertions))] | |
49 | cache_hits: 0, | |
50 | key_size: mem::size_of::<Q::Key>(), | |
51 | key_type: type_name::<Q::Key>(), | |
52 | value_size: mem::size_of::<Q::Value>(), | |
53 | value_type: type_name::<Q::Value>(), | |
54 | entry_count: map.iter_results(|results| results.count()), | |
55 | local_def_id_keys: None, | |
56 | }; | |
57 | map.iter_results(|results| { | |
58 | for (key, _, _) in results { | |
59 | key.key_stats(&mut stats) | |
60 | } | |
61 | }); | |
62 | stats | |
63 | } | |
64 | ||
65 | pub fn print_stats(tcx: TyCtxt<'_>) { | |
66 | let queries = query_stats(tcx); | |
67 | ||
68 | if cfg!(debug_assertions) { | |
69 | let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); | |
70 | let results: usize = queries.iter().map(|s| s.entry_count).sum(); | |
71 | println!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64); | |
72 | } | |
73 | ||
74 | let mut query_key_sizes = queries.clone(); | |
75 | query_key_sizes.sort_by_key(|q| q.key_size); | |
76 | println!("\nLarge query keys:"); | |
77 | for q in query_key_sizes.iter().rev().filter(|q| q.key_size > 8) { | |
78 | println!(" {} - {} x {} - {}", q.name, q.key_size, q.entry_count, q.key_type); | |
79 | } | |
80 | ||
81 | let mut query_value_sizes = queries.clone(); | |
82 | query_value_sizes.sort_by_key(|q| q.value_size); | |
83 | println!("\nLarge query values:"); | |
84 | for q in query_value_sizes.iter().rev().filter(|q| q.value_size > 8) { | |
85 | println!(" {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type); | |
86 | } | |
87 | ||
88 | if cfg!(debug_assertions) { | |
89 | let mut query_cache_hits = queries.clone(); | |
90 | query_cache_hits.sort_by_key(|q| q.cache_hits); | |
91 | println!("\nQuery cache hits:"); | |
92 | for q in query_cache_hits.iter().rev() { | |
93 | println!( | |
94 | " {} - {} ({}%)", | |
95 | q.name, | |
96 | q.cache_hits, | |
97 | q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64 | |
98 | ); | |
99 | } | |
100 | } | |
101 | ||
102 | let mut query_value_count = queries.clone(); | |
103 | query_value_count.sort_by_key(|q| q.entry_count); | |
104 | println!("\nQuery value count:"); | |
105 | for q in query_value_count.iter().rev() { | |
106 | println!(" {} - {}", q.name, q.entry_count); | |
107 | } | |
108 | ||
109 | let mut def_id_density: Vec<_> = | |
110 | queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect(); | |
111 | def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap()); | |
112 | println!("\nLocal DefId density:"); | |
113 | let total = tcx.hir().definitions().def_index_count() as f64; | |
114 | for q in def_id_density.iter().rev() { | |
115 | let local = q.local_def_id_keys.unwrap(); | |
116 | println!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total); | |
117 | } | |
118 | } | |
119 | ||
120 | macro_rules! print_stats { | |
121 | (<$tcx:tt> $($category:tt { | |
122 | $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* | |
123 | },)*) => { | |
124 | fn query_stats(tcx: TyCtxt<'_>) -> Vec<QueryStats> { | |
125 | let mut queries = Vec::new(); | |
126 | ||
127 | $($( | |
128 | queries.push(stats::<queries::$name<'_>>( | |
129 | stringify!($name), | |
130 | &tcx.queries.$name, | |
131 | )); | |
132 | )*)* | |
133 | ||
134 | queries | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | rustc_query_append! { [print_stats!][<'tcx>] } |