diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index dc1ceaf69f0..97a1c83dbff 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1467,6 +1467,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "inject the given attribute in the crate"), self_profile: bool = (false, parse_bool, [UNTRACKED], "run the self profiler and output the raw event data"), + self_profile_events: Option> = (None, parse_opt_comma_list, [UNTRACKED], + "specifies which kinds of events get recorded by the self profiler"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emits a section containing stack size metadata"), plt: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index eed516a4381..eecd5cba6d3 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1138,7 +1138,7 @@ fn build_session_( ) -> Session { let self_profiler = if sopts.debugging_opts.self_profile { - let profiler = SelfProfiler::new(); + let profiler = SelfProfiler::new(&sopts.debugging_opts.self_profile_events); match profiler { Ok(profiler) => { crate::ty::query::QueryName::register_with_profiler(&profiler); diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index aabf9a401c6..585970e64df 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -27,26 +27,42 @@ pub enum ProfileCategory { Other, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum ProfilerEvent { - QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 }, - GenericActivityStart { category: ProfileCategory, label: Cow<'static, str>, time: u64 }, - GenericActivityEnd { category: ProfileCategory, label: Cow<'static, str>, time: u64 }, - IncrementalLoadResultStart { query_name: &'static str, time: u64 }, - IncrementalLoadResultEnd { query_name: &'static str, time: u64 }, - QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryCount { query_name: &'static str, category: ProfileCategory, count: usize, time: u64 }, - QueryBlockedStart { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: u64 }, +bitflags! { + struct EventFilter: u32 { + const GENERIC_ACTIVITIES = 1 << 0; + const QUERY_PROVIDERS = 1 << 1; + const QUERY_CACHE_HITS = 1 << 2; + const QUERY_BLOCKED = 1 << 3; + const INCR_CACHE_LOADS = 1 << 4; + + const DEFAULT = Self::GENERIC_ACTIVITIES.bits | + Self::QUERY_PROVIDERS.bits | + Self::QUERY_BLOCKED.bits | + Self::INCR_CACHE_LOADS.bits; + + // empty() and none() aren't const-fns unfortunately + const NONE = 0; + const ALL = !Self::NONE.bits; + } } +const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ + ("none", EventFilter::NONE), + ("all", EventFilter::ALL), + ("generic-activity", EventFilter::GENERIC_ACTIVITIES), + ("query-provider", EventFilter::QUERY_PROVIDERS), + ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), + ("query-blocked" , EventFilter::QUERY_BLOCKED), + ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), +]; + fn thread_id_to_u64(tid: ThreadId) -> u64 { unsafe { mem::transmute::(tid) } } pub struct SelfProfiler { profiler: Profiler, + event_filter_mask: EventFilter, query_event_kind: StringId, generic_activity_event_kind: StringId, incremental_load_result_event_kind: StringId, @@ -55,7 +71,7 @@ pub struct SelfProfiler { } impl SelfProfiler { - pub fn new() -> Result> { + pub fn new(event_filters: &Option>) -> Result> { let filename = format!("pid-{}.rustc_profile", process::id()); let path = std::path::Path::new(&filename); let profiler = Profiler::new(path)?; @@ -66,8 +82,38 @@ impl SelfProfiler { let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); + let mut event_filter_mask = EventFilter::empty(); + + if let Some(ref event_filters) = *event_filters { + let mut unknown_events = vec![]; + for item in event_filters { + if let Some(&(_, mask)) = EVENT_FILTERS_BY_NAME.iter() + .find(|&(name, _)| name == item) { + event_filter_mask |= mask; + } else { + unknown_events.push(item.clone()); + } + } + + // Warn about any unknown event names + if unknown_events.len() > 0 { + unknown_events.sort(); + unknown_events.dedup(); + + warn!("Unknown self-profiler events specified: {}. Available options are: {}.", + unknown_events.join(", "), + EVENT_FILTERS_BY_NAME.iter() + .map(|&(name, _)| name.to_string()) + .collect::>() + .join(", ")); + } + } else { + event_filter_mask = EventFilter::DEFAULT; + } + Ok(SelfProfiler { profiler, + event_filter_mask, query_event_kind, generic_activity_event_kind, incremental_load_result_event_kind, @@ -86,7 +132,6 @@ impl SelfProfiler { pub fn register_query_name(&self, query_name: QueryName) { let id = SelfProfiler::get_query_name_string_id(query_name); - self.profiler.alloc_string_with_reserved_id(id, query_name.as_str()); } @@ -95,7 +140,9 @@ impl SelfProfiler { &self, label: impl Into>, ) { - self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start); + } } #[inline] @@ -103,46 +150,66 @@ impl SelfProfiler { &self, label: impl Into>, ) { - self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End); + } } #[inline] pub fn record_query_hit(&self, query_name: QueryName) { - self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant); + if self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS) { + self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant); + } } #[inline] pub fn start_query(&self, query_name: QueryName) { - self.record_query(query_name, self.query_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::Start); + } } #[inline] pub fn end_query(&self, query_name: QueryName) { - self.record_query(query_name, self.query_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::End); + } } #[inline] pub fn incremental_load_result_start(&self, query_name: QueryName) { - self.record_query( - query_name, - self.incremental_load_result_event_kind, - TimestampKind::Start - ); + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::Start + ); + } } #[inline] pub fn incremental_load_result_end(&self, query_name: QueryName) { - self.record_query(query_name, self.incremental_load_result_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::End + ); + } } #[inline] pub fn query_blocked_start(&self, query_name: QueryName) { - self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start); + } } #[inline] pub fn query_blocked_end(&self, query_name: QueryName) { - self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End); + } } #[inline]