]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_query_impl/src/profiling_support.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_query_impl / src / profiling_support.rs
CommitLineData
2b03887a 1use crate::QueryCtxt;
dfeec247
XL
2use measureme::{StringComponent, StringId};
3use rustc_data_structures::fx::FxHashMap;
4use rustc_data_structures::profiling::SelfProfiler;
04454e1e 5use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
ba9703b0 6use rustc_hir::definitions::DefPathData;
6a06907d 7use rustc_middle::ty::{TyCtxt, WithOptConstParam};
5e7ed085 8use rustc_query_system::query::QueryCache;
dfeec247
XL
9use std::fmt::Debug;
10use std::io::Write;
11
2b03887a 12pub(crate) struct QueryKeyStringCache {
dfeec247
XL
13 def_id_cache: FxHashMap<DefId, StringId>,
14}
15
16impl QueryKeyStringCache {
6a06907d 17 fn new() -> QueryKeyStringCache {
dfeec247
XL
18 QueryKeyStringCache { def_id_cache: Default::default() }
19 }
20}
21
487cf647 22struct QueryKeyStringBuilder<'p, 'tcx> {
dfeec247
XL
23 profiler: &'p SelfProfiler,
24 tcx: TyCtxt<'tcx>,
487cf647 25 string_cache: &'p mut QueryKeyStringCache,
dfeec247
XL
26}
27
487cf647 28impl<'p, 'tcx> QueryKeyStringBuilder<'p, 'tcx> {
6a06907d 29 fn new(
dfeec247
XL
30 profiler: &'p SelfProfiler,
31 tcx: TyCtxt<'tcx>,
487cf647
FG
32 string_cache: &'p mut QueryKeyStringCache,
33 ) -> QueryKeyStringBuilder<'p, 'tcx> {
dfeec247
XL
34 QueryKeyStringBuilder { profiler, tcx, string_cache }
35 }
36
37 // The current implementation is rather crude. In the future it might be a
38 // good idea to base this on `ty::print` in order to get nicer and more
39 // efficient query keys.
40 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];
1b1a35ee
XL
57 let crate_name;
58 let other_name;
dfeec247
XL
59 let name;
60 let dis;
61 let end_index;
62
63 match def_key.disambiguated_data.data {
64 DefPathData::CrateRoot => {
a2a8927a
XL
65 crate_name = self.tcx.crate_name(def_id.krate);
66 name = crate_name.as_str();
dfeec247
XL
67 dis = "";
68 end_index = 3;
69 }
70 other => {
1b1a35ee
XL
71 other_name = other.to_string();
72 name = other_name.as_str();
dfeec247
XL
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("::"),
3dfed10e 89 StringComponent::Value(name),
dfeec247
XL
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
6a06907d 101trait IntoSelfProfilingString {
487cf647 102 fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
dfeec247
XL
103}
104
105// The default implementation of `IntoSelfProfilingString` just uses `Debug`
106// which is slow and causes lots of duplication of string data.
107// The specialized impls below take care of making the `DefId` case more
108// efficient.
109impl<T: Debug> IntoSelfProfilingString for T {
110 default fn to_self_profile_string(
111 &self,
487cf647 112 builder: &mut QueryKeyStringBuilder<'_, '_>,
dfeec247 113 ) -> StringId {
9c376795 114 let s = format!("{self:?}");
dfeec247
XL
115 builder.profiler.alloc_string(&s[..])
116 }
117}
118
f035d41b 119impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
487cf647 120 fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
f035d41b
XL
121 self.spec_to_self_profile_string(builder)
122 }
123}
124
125#[rustc_specialization_trait]
6a06907d 126trait SpecIntoSelfProfilingString: Debug {
487cf647 127 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
f035d41b
XL
128}
129
130impl SpecIntoSelfProfilingString for DefId {
487cf647 131 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
dfeec247
XL
132 builder.def_id_to_string_id(*self)
133 }
134}
135
f035d41b 136impl SpecIntoSelfProfilingString for CrateNum {
487cf647 137 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
04454e1e 138 builder.def_id_to_string_id(self.as_def_id())
dfeec247
XL
139 }
140}
141
f035d41b 142impl SpecIntoSelfProfilingString for DefIndex {
487cf647 143 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
dfeec247
XL
144 builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
145 }
146}
147
3dfed10e 148impl SpecIntoSelfProfilingString for LocalDefId {
487cf647 149 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
3dfed10e
XL
150 builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
151 }
152}
153
154impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
487cf647 155 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
3dfed10e
XL
156 // We print `WithOptConstParam` values as tuples to make them shorter
157 // and more readable, without losing information:
158 //
159 // "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
160 // becomes "(foo::bar, foo::baz)" and
161 // "WithOptConstParam { did: foo::bar, const_param_did: None }"
162 // becomes "(foo::bar, _)".
163
164 let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
165
166 let const_param_did = if let Some(const_param_did) = self.const_param_did {
167 let const_param_did = builder.def_id_to_string_id(const_param_did);
168 StringComponent::Ref(const_param_did)
169 } else {
170 StringComponent::Value("_")
171 };
172
173 let components = [
174 StringComponent::Value("("),
175 did,
176 StringComponent::Value(", "),
177 const_param_did,
178 StringComponent::Value(")"),
179 ];
180
181 builder.profiler.alloc_string(&components[..])
182 }
183}
184
f035d41b 185impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
dfeec247 186where
f035d41b
XL
187 T0: SpecIntoSelfProfilingString,
188 T1: SpecIntoSelfProfilingString,
dfeec247 189{
487cf647 190 fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
dfeec247
XL
191 let val0 = self.0.to_self_profile_string(builder);
192 let val1 = self.1.to_self_profile_string(builder);
193
194 let components = &[
195 StringComponent::Value("("),
196 StringComponent::Ref(val0),
197 StringComponent::Value(","),
198 StringComponent::Ref(val1),
199 StringComponent::Value(")"),
200 ];
201
202 builder.profiler.alloc_string(components)
203 }
204}
205
206/// Allocate the self-profiling query strings for a single query cache. This
207/// method is called from `alloc_self_profile_query_strings` which knows all
208/// the queries via macro magic.
2b03887a 209pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
dfeec247
XL
210 tcx: TyCtxt<'tcx>,
211 query_name: &'static str,
5e7ed085 212 query_cache: &C,
dfeec247
XL
213 string_cache: &mut QueryKeyStringCache,
214) where
ba9703b0
XL
215 C: QueryCache,
216 C::Key: Debug + Clone,
dfeec247
XL
217{
218 tcx.prof.with_profiler(|profiler| {
219 let event_id_builder = profiler.event_id_builder();
220
221 // Walk the entire query cache and allocate the appropriate
222 // string representations. Each cache entry is uniquely
223 // identified by its dep_node_index.
224 if profiler.query_key_recording_enabled() {
225 let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);
226
227 let query_name = profiler.get_or_alloc_cached_string(query_name);
228
229 // Since building the string representation of query keys might
230 // need to invoke queries itself, we cannot keep the query caches
231 // locked while doing so. Instead we copy out the
232 // `(query_key, dep_node_index)` pairs and release the lock again.
cdc7bbd5 233 let mut query_keys_and_indices = Vec::new();
5e7ed085 234 query_cache.iter(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i)));
dfeec247
XL
235
236 // Now actually allocate the strings. If allocating the strings
237 // generates new entries in the query cache, we'll miss them but
238 // we don't actually care.
239 for (query_key, dep_node_index) in query_keys_and_indices {
240 // Translate the DepNodeIndex into a QueryInvocationId
241 let query_invocation_id = dep_node_index.into();
242
243 // Create the string version of the query-key
244 let query_key = query_key.to_self_profile_string(&mut query_string_builder);
245 let event_id = event_id_builder.from_label_and_arg(query_name, query_key);
246
247 // Doing this in bulk might be a good idea:
248 profiler.map_query_invocation_id_to_string(
249 query_invocation_id,
250 event_id.to_string_id(),
251 );
252 }
253 } else {
254 // In this branch we don't allocate query keys
255 let query_name = profiler.get_or_alloc_cached_string(query_name);
256 let event_id = event_id_builder.from_label(query_name).to_string_id();
257
923072b8
FG
258 // FIXME(eddyb) make this O(1) by using a pre-cached query name `EventId`,
259 // instead of passing the `DepNodeIndex` to `finish_with_query_invocation_id`,
260 // when recording the event in the first place.
cdc7bbd5 261 let mut query_invocation_ids = Vec::new();
5e7ed085 262 query_cache.iter(&mut |_, _, i| {
cdc7bbd5 263 query_invocation_ids.push(i.into());
74b04a01 264 });
cdc7bbd5
XL
265
266 profiler.bulk_map_query_invocation_id_to_single_string(
267 query_invocation_ids.into_iter(),
268 event_id,
269 );
dfeec247
XL
270 }
271 });
272}
6a06907d
XL
273
274/// All self-profiling events generated by the query engine use
275/// virtual `StringId`s for their `event_id`. This method makes all
276/// those virtual `StringId`s point to actual strings.
277///
278/// If we are recording only summary data, the ids will point to
279/// just the query names. If we are recording query keys too, we
280/// allocate the corresponding strings here.
9c376795 281pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
6a06907d
XL
282 if !tcx.prof.enabled() {
283 return;
284 }
285
286 let mut string_cache = QueryKeyStringCache::new();
2b03887a 287 let queries = QueryCtxt::from_tcx(tcx);
6a06907d 288
2b03887a
FG
289 for query in &queries.queries.query_structs {
290 (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
6a06907d 291 }
6a06907d 292}