"graphviz",
"jobserver",
"log",
- "measureme",
"num_cpus",
"parking_lot 0.9.0",
"polonius-engine",
name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
+ "bitflags",
"cfg-if",
"crossbeam-utils 0.6.5",
"ena",
"jobserver",
"lazy_static 1.3.0",
"log",
+ "measureme",
"parking_lot 0.9.0",
"rustc-hash",
"rustc-rayon 0.3.0",
chalk-engine = { version = "0.9.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-measureme = "0.4"
pub mod captures;
pub mod common;
pub mod nodemap;
- pub mod profiling;
pub mod bug;
}
use syntax::sess::{ParseSess, ProcessCfgMod};
use syntax::symbol::Symbol;
use syntax_pos::{MultiSpan, Span};
-use crate::util::profiling::{SelfProfiler, SelfProfilerRef};
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
use rustc_data_structures::flock;
use rustc_data_structures::jobserver;
+use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
use ::jobserver::Client;
use std;
use crate::util::common::ErrorReported;
use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap};
use crate::util::nodemap::{FxHashMap, FxHashSet};
-use crate::util::profiling::SelfProfilerRef;
use errors::DiagnosticBuilder;
use arena::SyncDroplessArena;
use smallvec::SmallVec;
+use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{
HashStable, StableHasher, StableVec, hash_stable_hashmap,
};
use crate::ty::query::{Query, QueryName};
use crate::ty::query::QueryCache;
use crate::ty::query::plumbing::CycleError;
-use crate::util::profiling::ProfileCategory;
+use rustc_data_structures::profiling::ProfileCategory;
use std::borrow::Cow;
use std::hash::Hash;
use crate::ty::subst::SubstsRef;
use crate::util::nodemap::{DefIdSet, DefIdMap};
use crate::util::common::ErrorReported;
-use crate::util::profiling::ProfileCategory::*;
+use rustc_data_structures::profiling::ProfileCategory::*;
use rustc_data_structures::svh::Svh;
use rustc_index::vec::IndexVec;
rustc_data_structures::stable_hasher::StableHasher,
ich::StableHashingContext
};
- use crate::util::profiling::ProfileCategory;
+ use rustc_data_structures::profiling::ProfileCategory;
define_queries_struct! {
tcx: $tcx,
$($name),*
}
+ impl rustc_data_structures::profiling::QueryName for QueryName {
+ fn discriminant(self) -> std::mem::Discriminant<QueryName> {
+ std::mem::discriminant(&self)
+ }
+
+ fn as_str(self) -> &'static str {
+ QueryName::as_str(&self)
+ }
+ }
+
impl QueryName {
- pub fn register_with_profiler(profiler: &crate::util::profiling::SelfProfiler) {
+ pub fn register_with_profiler(profiler: &rustc_data_structures::profiling::SelfProfiler) {
$(profiler.register_query_name(QueryName::$name);)*
}
+++ /dev/null
-use std::error::Error;
-use std::fs;
-use std::mem::{self, Discriminant};
-use std::path::Path;
-use std::process;
-use std::sync::Arc;
-use std::thread::ThreadId;
-use std::u32;
-
-use crate::ty::query::QueryName;
-
-use measureme::{StringId, TimestampKind};
-
-/// MmapSerializatioSink is faster on macOS and Linux
-/// but FileSerializationSink is faster on Windows
-#[cfg(not(windows))]
-type SerializationSink = measureme::MmapSerializationSink;
-#[cfg(windows)]
-type SerializationSink = measureme::FileSerializationSink;
-
-type Profiler = measureme::Profiler<SerializationSink>;
-
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
-pub enum ProfileCategory {
- Parsing,
- Expansion,
- TypeChecking,
- BorrowChecking,
- Codegen,
- Linking,
- Other,
-}
-
-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::<ThreadId, u64>(tid) }
-}
-
-
-/// A reference to the SelfProfiler. It can be cloned and sent across thread
-/// boundaries at will.
-#[derive(Clone)]
-pub struct SelfProfilerRef {
- // This field is `None` if self-profiling is disabled for the current
- // compilation session.
- profiler: Option<Arc<SelfProfiler>>,
-
- // We store the filter mask directly in the reference because that doesn't
- // cost anything and allows for filtering with checking if the profiler is
- // actually enabled.
- event_filter_mask: EventFilter,
-}
-
-impl SelfProfilerRef {
-
- pub fn new(profiler: Option<Arc<SelfProfiler>>) -> SelfProfilerRef {
- // If there is no SelfProfiler then the filter mask is set to NONE,
- // ensuring that nothing ever tries to actually access it.
- let event_filter_mask = profiler
- .as_ref()
- .map(|p| p.event_filter_mask)
- .unwrap_or(EventFilter::NONE);
-
- SelfProfilerRef {
- profiler,
- event_filter_mask,
- }
- }
-
- // This shim makes sure that calls only get executed if the filter mask
- // lets them pass. It also contains some trickery to make sure that
- // code is optimized for non-profiling compilation sessions, i.e. anything
- // past the filter check is never inlined so it doesn't clutter the fast
- // path.
- #[inline(always)]
- fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
- where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>
- {
- #[inline(never)]
- fn cold_call<F>(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_>
- where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>
- {
- let profiler = profiler_ref.profiler.as_ref().unwrap();
- f(&**profiler)
- }
-
- if unlikely!(self.event_filter_mask.contains(event_filter)) {
- cold_call(self, f)
- } else {
- TimingGuard::none()
- }
- }
-
- /// Start profiling a generic activity. Profiling continues until the
- /// TimingGuard returned from this call is dropped.
- #[inline(always)]
- pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> {
- self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
- let event_id = profiler.profiler.alloc_string(event_id);
- TimingGuard::start(
- profiler,
- profiler.generic_activity_event_kind,
- event_id
- )
- })
- }
-
- /// Start profiling a query provider. Profiling continues until the
- /// TimingGuard returned from this call is dropped.
- #[inline(always)]
- pub fn query_provider(&self, query_name: QueryName) -> TimingGuard<'_> {
- self.exec(EventFilter::QUERY_PROVIDERS, |profiler| {
- let event_id = SelfProfiler::get_query_name_string_id(query_name);
- TimingGuard::start(profiler, profiler.query_event_kind, event_id)
- })
- }
-
- /// Record a query in-memory cache hit.
- #[inline(always)]
- pub fn query_cache_hit(&self, query_name: QueryName) {
- self.non_guard_query_event(
- |profiler| profiler.query_cache_hit_event_kind,
- query_name,
- EventFilter::QUERY_CACHE_HITS,
- TimestampKind::Instant,
- );
- }
-
- /// Start profiling a query being blocked on a concurrent execution.
- /// Profiling continues until the TimingGuard returned from this call is
- /// dropped.
- #[inline(always)]
- pub fn query_blocked(&self, query_name: QueryName) -> TimingGuard<'_> {
- self.exec(EventFilter::QUERY_BLOCKED, |profiler| {
- let event_id = SelfProfiler::get_query_name_string_id(query_name);
- TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id)
- })
- }
-
- /// Start profiling how long it takes to load a query result from the
- /// incremental compilation on-disk cache. Profiling continues until the
- /// TimingGuard returned from this call is dropped.
- #[inline(always)]
- pub fn incr_cache_loading(&self, query_name: QueryName) -> TimingGuard<'_> {
- self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| {
- let event_id = SelfProfiler::get_query_name_string_id(query_name);
- TimingGuard::start(
- profiler,
- profiler.incremental_load_result_event_kind,
- event_id
- )
- })
- }
-
- #[inline(always)]
- fn non_guard_query_event(
- &self,
- event_kind: fn(&SelfProfiler) -> StringId,
- query_name: QueryName,
- event_filter: EventFilter,
- timestamp_kind: TimestampKind
- ) {
- drop(self.exec(event_filter, |profiler| {
- let event_id = SelfProfiler::get_query_name_string_id(query_name);
- let thread_id = thread_id_to_u64(std::thread::current().id());
-
- profiler.profiler.record_event(
- event_kind(profiler),
- event_id,
- thread_id,
- timestamp_kind,
- );
-
- TimingGuard::none()
- }));
- }
-}
-
-pub struct SelfProfiler {
- profiler: Profiler,
- event_filter_mask: EventFilter,
- query_event_kind: StringId,
- generic_activity_event_kind: StringId,
- incremental_load_result_event_kind: StringId,
- query_blocked_event_kind: StringId,
- query_cache_hit_event_kind: StringId,
-}
-
-impl SelfProfiler {
- pub fn new(
- output_directory: &Path,
- crate_name: Option<&str>,
- event_filters: &Option<Vec<String>>
- ) -> Result<SelfProfiler, Box<dyn Error>> {
- fs::create_dir_all(output_directory)?;
-
- let crate_name = crate_name.unwrap_or("unknown-crate");
- let filename = format!("{}-{}.rustc_profile", crate_name, process::id());
- let path = output_directory.join(&filename);
- let profiler = Profiler::new(&path)?;
-
- let query_event_kind = profiler.alloc_string("Query");
- let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
- let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
- 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::<Vec<_>>()
- .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,
- query_blocked_event_kind,
- query_cache_hit_event_kind,
- })
- }
-
- fn get_query_name_string_id(query_name: QueryName) -> StringId {
- let discriminant = unsafe {
- mem::transmute::<Discriminant<QueryName>, u64>(mem::discriminant(&query_name))
- };
-
- StringId::reserved(discriminant as u32)
- }
-
- 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());
- }
-}
-
-#[must_use]
-pub struct TimingGuard<'a>(Option<measureme::TimingGuard<'a, SerializationSink>>);
-
-impl<'a> TimingGuard<'a> {
- #[inline]
- pub fn start(
- profiler: &'a SelfProfiler,
- event_kind: StringId,
- event_id: StringId,
- ) -> TimingGuard<'a> {
- let thread_id = thread_id_to_u64(std::thread::current().id());
- let raw_profiler = &profiler.profiler;
- let timing_guard = raw_profiler.start_recording_interval_event(event_kind,
- event_id,
- thread_id);
- TimingGuard(Some(timing_guard))
- }
-
- #[inline]
- pub fn none() -> TimingGuard<'a> {
- TimingGuard(None)
- }
-}
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc::ty::TyCtxt;
use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
-use rustc::util::profiling::SelfProfilerRef;
+use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_fs_util::link_or_copy;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
rustc-hash = "1.0.1"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_index = { path = "../librustc_index", package = "rustc_index" }
+bitflags = "1.2.1"
+measureme = "0.4"
[dependencies.parking_lot]
version = "0.9"
pub mod vec_linked_list;
pub mod work_queue;
pub mod fingerprint;
+pub mod profiling;
pub struct OnDrop<F: Fn()>(pub F);
--- /dev/null
+use std::error::Error;
+use std::fs;
+use std::mem::{self, Discriminant};
+use std::path::Path;
+use std::process;
+use std::sync::Arc;
+use std::thread::ThreadId;
+use std::u32;
+
+use measureme::{StringId, TimestampKind};
+
+/// MmapSerializatioSink is faster on macOS and Linux
+/// but FileSerializationSink is faster on Windows
+#[cfg(not(windows))]
+type SerializationSink = measureme::MmapSerializationSink;
+#[cfg(windows)]
+type SerializationSink = measureme::FileSerializationSink;
+
+type Profiler = measureme::Profiler<SerializationSink>;
+
+pub trait QueryName: Sized + Copy {
+ fn discriminant(self) -> Discriminant<Self>;
+ fn as_str(self) -> &'static str;
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
+pub enum ProfileCategory {
+ Parsing,
+ Expansion,
+ TypeChecking,
+ BorrowChecking,
+ Codegen,
+ Linking,
+ Other,
+}
+
+bitflags::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::<ThreadId, u64>(tid) }
+}
+
+
+/// A reference to the SelfProfiler. It can be cloned and sent across thread
+/// boundaries at will.
+#[derive(Clone)]
+pub struct SelfProfilerRef {
+ // This field is `None` if self-profiling is disabled for the current
+ // compilation session.
+ profiler: Option<Arc<SelfProfiler>>,
+
+ // We store the filter mask directly in the reference because that doesn't
+ // cost anything and allows for filtering with checking if the profiler is
+ // actually enabled.
+ event_filter_mask: EventFilter,
+}
+
+impl SelfProfilerRef {
+
+ pub fn new(profiler: Option<Arc<SelfProfiler>>) -> SelfProfilerRef {
+ // If there is no SelfProfiler then the filter mask is set to NONE,
+ // ensuring that nothing ever tries to actually access it.
+ let event_filter_mask = profiler
+ .as_ref()
+ .map(|p| p.event_filter_mask)
+ .unwrap_or(EventFilter::NONE);
+
+ SelfProfilerRef {
+ profiler,
+ event_filter_mask,
+ }
+ }
+
+ // This shim makes sure that calls only get executed if the filter mask
+ // lets them pass. It also contains some trickery to make sure that
+ // code is optimized for non-profiling compilation sessions, i.e. anything
+ // past the filter check is never inlined so it doesn't clutter the fast
+ // path.
+ #[inline(always)]
+ fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
+ where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>
+ {
+ #[inline(never)]
+ fn cold_call<F>(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_>
+ where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>
+ {
+ let profiler = profiler_ref.profiler.as_ref().unwrap();
+ f(&**profiler)
+ }
+
+ if unlikely!(self.event_filter_mask.contains(event_filter)) {
+ cold_call(self, f)
+ } else {
+ TimingGuard::none()
+ }
+ }
+
+ /// Start profiling a generic activity. Profiling continues until the
+ /// TimingGuard returned from this call is dropped.
+ #[inline(always)]
+ pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> {
+ self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
+ let event_id = profiler.profiler.alloc_string(event_id);
+ TimingGuard::start(
+ profiler,
+ profiler.generic_activity_event_kind,
+ event_id
+ )
+ })
+ }
+
+ /// Start profiling a query provider. Profiling continues until the
+ /// TimingGuard returned from this call is dropped.
+ #[inline(always)]
+ pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+ self.exec(EventFilter::QUERY_PROVIDERS, |profiler| {
+ let event_id = SelfProfiler::get_query_name_string_id(query_name);
+ TimingGuard::start(profiler, profiler.query_event_kind, event_id)
+ })
+ }
+
+ /// Record a query in-memory cache hit.
+ #[inline(always)]
+ pub fn query_cache_hit(&self, query_name: impl QueryName) {
+ self.non_guard_query_event(
+ |profiler| profiler.query_cache_hit_event_kind,
+ query_name,
+ EventFilter::QUERY_CACHE_HITS,
+ TimestampKind::Instant,
+ );
+ }
+
+ /// Start profiling a query being blocked on a concurrent execution.
+ /// Profiling continues until the TimingGuard returned from this call is
+ /// dropped.
+ #[inline(always)]
+ pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+ self.exec(EventFilter::QUERY_BLOCKED, |profiler| {
+ let event_id = SelfProfiler::get_query_name_string_id(query_name);
+ TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id)
+ })
+ }
+
+ /// Start profiling how long it takes to load a query result from the
+ /// incremental compilation on-disk cache. Profiling continues until the
+ /// TimingGuard returned from this call is dropped.
+ #[inline(always)]
+ pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+ self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| {
+ let event_id = SelfProfiler::get_query_name_string_id(query_name);
+ TimingGuard::start(
+ profiler,
+ profiler.incremental_load_result_event_kind,
+ event_id
+ )
+ })
+ }
+
+ #[inline(always)]
+ fn non_guard_query_event(
+ &self,
+ event_kind: fn(&SelfProfiler) -> StringId,
+ query_name: impl QueryName,
+ event_filter: EventFilter,
+ timestamp_kind: TimestampKind
+ ) {
+ drop(self.exec(event_filter, |profiler| {
+ let event_id = SelfProfiler::get_query_name_string_id(query_name);
+ let thread_id = thread_id_to_u64(std::thread::current().id());
+
+ profiler.profiler.record_event(
+ event_kind(profiler),
+ event_id,
+ thread_id,
+ timestamp_kind,
+ );
+
+ TimingGuard::none()
+ }));
+ }
+}
+
+pub struct SelfProfiler {
+ profiler: Profiler,
+ event_filter_mask: EventFilter,
+ query_event_kind: StringId,
+ generic_activity_event_kind: StringId,
+ incremental_load_result_event_kind: StringId,
+ query_blocked_event_kind: StringId,
+ query_cache_hit_event_kind: StringId,
+}
+
+impl SelfProfiler {
+ pub fn new(
+ output_directory: &Path,
+ crate_name: Option<&str>,
+ event_filters: &Option<Vec<String>>
+ ) -> Result<SelfProfiler, Box<dyn Error>> {
+ fs::create_dir_all(output_directory)?;
+
+ let crate_name = crate_name.unwrap_or("unknown-crate");
+ let filename = format!("{}-{}.rustc_profile", crate_name, process::id());
+ let path = output_directory.join(&filename);
+ let profiler = Profiler::new(&path)?;
+
+ let query_event_kind = profiler.alloc_string("Query");
+ let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
+ let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
+ 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::<Vec<_>>()
+ .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,
+ query_blocked_event_kind,
+ query_cache_hit_event_kind,
+ })
+ }
+
+ fn get_query_name_string_id(query_name: impl QueryName) -> StringId {
+ let discriminant = unsafe {
+ mem::transmute::<Discriminant<_>, u64>(query_name.discriminant())
+ };
+
+ StringId::reserved(discriminant as u32)
+ }
+
+ pub fn register_query_name(&self, query_name: impl QueryName) {
+ let id = SelfProfiler::get_query_name_string_id(query_name);
+ self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
+ }
+}
+
+#[must_use]
+pub struct TimingGuard<'a>(Option<measureme::TimingGuard<'a, SerializationSink>>);
+
+impl<'a> TimingGuard<'a> {
+ #[inline]
+ pub fn start(
+ profiler: &'a SelfProfiler,
+ event_kind: StringId,
+ event_id: StringId,
+ ) -> TimingGuard<'a> {
+ let thread_id = thread_id_to_u64(std::thread::current().id());
+ let raw_profiler = &profiler.profiler;
+ let timing_guard = raw_profiler.start_recording_interval_event(event_kind,
+ event_id,
+ thread_id);
+ TimingGuard(Some(timing_guard))
+ }
+
+ #[inline]
+ pub fn none() -> TimingGuard<'a> {
+ TimingGuard(None)
+ }
+}