]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/profiling.rs
Rollup merge of #59748 - agnxy:trademark, r=skade
[rust.git] / src / librustc / util / profiling.rs
1 use std::borrow::Cow;
2 use std::error::Error;
3 use std::mem::{self, Discriminant};
4 use std::process;
5 use std::thread::ThreadId;
6 use std::u32;
7
8 use crate::ty::query::QueryName;
9
10 use measureme::{StringId, TimestampKind};
11
12 /// MmapSerializatioSink is faster on macOS and Linux
13 /// but FileSerializationSink is faster on Windows
14 #[cfg(not(windows))]
15 type Profiler = measureme::Profiler<measureme::MmapSerializationSink>;
16 #[cfg(windows)]
17 type Profiler = measureme::Profiler<measureme::FileSerializationSink>;
18
19 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
20 pub enum ProfileCategory {
21     Parsing,
22     Expansion,
23     TypeChecking,
24     BorrowChecking,
25     Codegen,
26     Linking,
27     Other,
28 }
29
30 #[derive(Clone, Debug, Eq, PartialEq)]
31 pub enum ProfilerEvent {
32     QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 },
33     QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
34     GenericActivityStart { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
35     GenericActivityEnd { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
36     IncrementalLoadResultStart { query_name: &'static str, time: u64 },
37     IncrementalLoadResultEnd { query_name: &'static str, time: u64 },
38     QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 },
39     QueryCount { query_name: &'static str, category: ProfileCategory, count: usize, time: u64 },
40     QueryBlockedStart { query_name: &'static str, category: ProfileCategory, time: u64 },
41     QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
42 }
43
44 fn thread_id_to_u64(tid: ThreadId) -> u64 {
45     unsafe { mem::transmute::<ThreadId, u64>(tid) }
46 }
47
48 pub struct SelfProfiler {
49     profiler: Profiler,
50     query_event_kind: StringId,
51     generic_activity_event_kind: StringId,
52     incremental_load_result_event_kind: StringId,
53     query_blocked_event_kind: StringId,
54     query_cache_hit_event_kind: StringId,
55 }
56
57 impl SelfProfiler {
58     pub fn new() -> Result<SelfProfiler, Box<dyn Error>> {
59         let filename = format!("pid-{}.rustc_profile", process::id());
60         let path = std::path::Path::new(&filename);
61         let profiler = Profiler::new(path)?;
62
63         let query_event_kind = profiler.alloc_string("Query");
64         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
65         let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
66         let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
67         let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit");
68
69         Ok(SelfProfiler {
70             profiler,
71             query_event_kind,
72             generic_activity_event_kind,
73             incremental_load_result_event_kind,
74             query_blocked_event_kind,
75             query_cache_hit_event_kind,
76         })
77     }
78
79     fn get_query_name_string_id(query_name: QueryName) -> StringId {
80         let discriminant = unsafe {
81             mem::transmute::<Discriminant<QueryName>, u64>(mem::discriminant(&query_name))
82         };
83
84         StringId::reserved(discriminant as u32)
85     }
86
87     pub fn register_query_name(&self, query_name: QueryName) {
88         let id = SelfProfiler::get_query_name_string_id(query_name);
89
90         self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
91     }
92
93     #[inline]
94     pub fn start_activity(
95         &self,
96         label: impl Into<Cow<'static, str>>,
97     ) {
98         self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start);
99     }
100
101     #[inline]
102     pub fn end_activity(
103         &self,
104         label: impl Into<Cow<'static, str>>,
105     ) {
106         self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End);
107     }
108
109     #[inline]
110     pub fn record_query_hit(&self, query_name: QueryName) {
111         self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant);
112     }
113
114     #[inline]
115     pub fn start_query(&self, query_name: QueryName) {
116         self.record_query(query_name, self.query_event_kind, TimestampKind::Start);
117     }
118
119     #[inline]
120     pub fn end_query(&self, query_name: QueryName) {
121         self.record_query(query_name, self.query_event_kind, TimestampKind::End);
122     }
123
124     #[inline]
125     pub fn incremental_load_result_start(&self, query_name: QueryName) {
126         self.record_query(
127             query_name,
128             self.incremental_load_result_event_kind,
129             TimestampKind::Start
130         );
131     }
132
133     #[inline]
134     pub fn incremental_load_result_end(&self, query_name: QueryName) {
135         self.record_query(query_name, self.incremental_load_result_event_kind, TimestampKind::End);
136     }
137
138     #[inline]
139     pub fn query_blocked_start(&self, query_name: QueryName) {
140         self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start);
141     }
142
143     #[inline]
144     pub fn query_blocked_end(&self, query_name: QueryName) {
145         self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End);
146     }
147
148     #[inline]
149     fn record(&self, event_id: &str, event_kind: StringId, timestamp_kind: TimestampKind) {
150         let thread_id = thread_id_to_u64(std::thread::current().id());
151
152         let event_id = self.profiler.alloc_string(event_id);
153         self.profiler.record_event(event_kind, event_id, thread_id, timestamp_kind);
154     }
155
156     #[inline]
157     fn record_query(
158         &self,
159         query_name: QueryName,
160         event_kind: StringId,
161         timestamp_kind: TimestampKind,
162     ) {
163         let dep_node_name = SelfProfiler::get_query_name_string_id(query_name);
164
165         let thread_id = thread_id_to_u64(std::thread::current().id());
166
167         self.profiler.record_event(event_kind, dep_node_name, thread_id, timestamp_kind);
168     }
169 }