3 use std::mem::{self, Discriminant};
5 use std::thread::ThreadId;
8 use crate::ty::query::QueryName;
10 use measureme::{StringId, TimestampKind};
12 /// MmapSerializatioSink is faster on macOS and Linux
13 /// but FileSerializationSink is faster on Windows
15 type Profiler = measureme::Profiler<measureme::MmapSerializationSink>;
17 type Profiler = measureme::Profiler<measureme::FileSerializationSink>;
19 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
20 pub enum ProfileCategory {
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 },
44 fn thread_id_to_u64(tid: ThreadId) -> u64 {
45 unsafe { mem::transmute::<ThreadId, u64>(tid) }
48 pub struct SelfProfiler {
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,
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)?;
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");
72 generic_activity_event_kind,
73 incremental_load_result_event_kind,
74 query_blocked_event_kind,
75 query_cache_hit_event_kind,
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))
84 StringId::reserved(discriminant as u32)
87 pub fn register_query_name(&self, query_name: QueryName) {
88 let id = SelfProfiler::get_query_name_string_id(query_name);
90 self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
94 pub fn start_activity(
96 label: impl Into<Cow<'static, str>>,
98 self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start);
104 label: impl Into<Cow<'static, str>>,
106 self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End);
110 pub fn record_query_hit(&self, query_name: QueryName) {
111 self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant);
115 pub fn start_query(&self, query_name: QueryName) {
116 self.record_query(query_name, self.query_event_kind, TimestampKind::Start);
120 pub fn end_query(&self, query_name: QueryName) {
121 self.record_query(query_name, self.query_event_kind, TimestampKind::End);
125 pub fn incremental_load_result_start(&self, query_name: QueryName) {
128 self.incremental_load_result_event_kind,
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);
139 pub fn query_blocked_start(&self, query_name: QueryName) {
140 self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start);
144 pub fn query_blocked_end(&self, query_name: QueryName) {
145 self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End);
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());
152 let event_id = self.profiler.alloc_string(event_id);
153 self.profiler.record_event(event_kind, event_id, thread_id, timestamp_kind);
159 query_name: QueryName,
160 event_kind: StringId,
161 timestamp_kind: TimestampKind,
163 let dep_node_name = SelfProfiler::get_query_name_string_id(query_name);
165 let thread_id = thread_id_to_u64(std::thread::current().id());
167 self.profiler.record_event(event_kind, dep_node_name, thread_id, timestamp_kind);