rustc_query_impl/
profiling_support.rs
1use std::fmt::Debug;
2use std::io::Write;
3
4use measureme::{StringComponent, StringId};
5use rustc_data_structures::fx::FxHashMap;
6use rustc_data_structures::profiling::SelfProfiler;
7use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId};
8use rustc_hir::definitions::DefPathData;
9use rustc_middle::ty::TyCtxt;
10use rustc_query_system::query::QueryCache;
11
12pub(crate) struct QueryKeyStringCache {
13 def_id_cache: FxHashMap<DefId, StringId>,
14}
15
16impl QueryKeyStringCache {
17 fn new() -> QueryKeyStringCache {
18 QueryKeyStringCache { def_id_cache: Default::default() }
19 }
20}
21
22struct QueryKeyStringBuilder<'a, 'tcx> {
23 profiler: &'a SelfProfiler,
24 tcx: TyCtxt<'tcx>,
25 string_cache: &'a mut QueryKeyStringCache,
26}
27
28impl<'a, 'tcx> QueryKeyStringBuilder<'a, 'tcx> {
29 fn new(
30 profiler: &'a SelfProfiler,
31 tcx: TyCtxt<'tcx>,
32 string_cache: &'a mut QueryKeyStringCache,
33 ) -> QueryKeyStringBuilder<'a, 'tcx> {
34 QueryKeyStringBuilder { profiler, tcx, string_cache }
35 }
36
37 fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
41 if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
42 return string_id;
43 }
44
45 let def_key = self.tcx.def_key(def_id);
46
47 let (parent_string_id, start_index) = match def_key.parent {
48 Some(parent_index) => {
49 let parent_def_id = DefId { index: parent_index, krate: def_id.krate };
50
51 (self.def_id_to_string_id(parent_def_id), 0)
52 }
53 None => (StringId::INVALID, 2),
54 };
55
56 let dis_buffer = &mut [0u8; 16];
57 let crate_name;
58 let other_name;
59 let name;
60 let dis;
61 let end_index;
62
63 match def_key.disambiguated_data.data {
64 DefPathData::CrateRoot => {
65 crate_name = self.tcx.crate_name(def_id.krate);
66 name = crate_name.as_str();
67 dis = "";
68 end_index = 3;
69 }
70 other => {
71 other_name = other.to_string();
72 name = other_name.as_str();
73 if def_key.disambiguated_data.disambiguator == 0 {
74 dis = "";
75 end_index = 3;
76 } else {
77 write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
78 .unwrap();
79 let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
80 dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
81 end_index = 4;
82 }
83 }
84 }
85
86 let components = [
87 StringComponent::Ref(parent_string_id),
88 StringComponent::Value("::"),
89 StringComponent::Value(name),
90 StringComponent::Value(dis),
91 ];
92
93 let string_id = self.profiler.alloc_string(&components[start_index..end_index]);
94
95 self.string_cache.def_id_cache.insert(def_id, string_id);
96
97 string_id
98 }
99}
100
101trait IntoSelfProfilingString {
102 fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
103}
104
105impl<T: Debug> IntoSelfProfilingString for T {
110 default fn to_self_profile_string(
111 &self,
112 builder: &mut QueryKeyStringBuilder<'_, '_>,
113 ) -> StringId {
114 let s = format!("{self:?}");
115 builder.profiler.alloc_string(&s[..])
116 }
117}
118
119impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
120 fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
121 self.spec_to_self_profile_string(builder)
122 }
123}
124
125#[rustc_specialization_trait]
126trait SpecIntoSelfProfilingString: Debug {
127 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
128}
129
130impl SpecIntoSelfProfilingString for DefId {
131 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
132 builder.def_id_to_string_id(*self)
133 }
134}
135
136impl SpecIntoSelfProfilingString for CrateNum {
137 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
138 builder.def_id_to_string_id(self.as_def_id())
139 }
140}
141
142impl SpecIntoSelfProfilingString for DefIndex {
143 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
144 builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
145 }
146}
147
148impl SpecIntoSelfProfilingString for LocalDefId {
149 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
150 builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
151 }
152}
153
154impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
155where
156 T0: SpecIntoSelfProfilingString,
157 T1: SpecIntoSelfProfilingString,
158{
159 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
160 let val0 = self.0.to_self_profile_string(builder);
161 let val1 = self.1.to_self_profile_string(builder);
162
163 let components = &[
164 StringComponent::Value("("),
165 StringComponent::Ref(val0),
166 StringComponent::Value(","),
167 StringComponent::Ref(val1),
168 StringComponent::Value(")"),
169 ];
170
171 builder.profiler.alloc_string(components)
172 }
173}
174
175pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
179 tcx: TyCtxt<'tcx>,
180 query_name: &'static str,
181 query_cache: &C,
182 string_cache: &mut QueryKeyStringCache,
183) where
184 C: QueryCache,
185 C::Key: Debug + Clone,
186{
187 tcx.prof.with_profiler(|profiler| {
188 let event_id_builder = profiler.event_id_builder();
189
190 if profiler.query_key_recording_enabled() {
194 let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);
195
196 let query_name = profiler.get_or_alloc_cached_string(query_name);
197
198 let mut query_keys_and_indices = Vec::new();
203 query_cache.iter(&mut |k, _, i| query_keys_and_indices.push((*k, i)));
204
205 for (query_key, dep_node_index) in query_keys_and_indices {
209 let query_invocation_id = dep_node_index.into();
211
212 let query_key = query_key.to_self_profile_string(&mut query_string_builder);
214 let event_id = event_id_builder.from_label_and_arg(query_name, query_key);
215
216 profiler.map_query_invocation_id_to_string(
218 query_invocation_id,
219 event_id.to_string_id(),
220 );
221 }
222 } else {
223 let query_name = profiler.get_or_alloc_cached_string(query_name);
225 let event_id = event_id_builder.from_label(query_name).to_string_id();
226
227 let mut query_invocation_ids = Vec::new();
231 query_cache.iter(&mut |_, _, i| {
232 query_invocation_ids.push(i.into());
233 });
234
235 profiler.bulk_map_query_invocation_id_to_single_string(
236 query_invocation_ids.into_iter(),
237 event_id,
238 );
239 }
240 });
241}
242
243pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
251 if !tcx.prof.enabled() {
252 return;
253 }
254
255 let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings");
256
257 let mut string_cache = QueryKeyStringCache::new();
258
259 for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() {
260 alloc(tcx, &mut string_cache)
261 }
262}