Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Profile incremental compilation hashing fingerprints #86619

Merged
merged 2 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 49 additions & 11 deletions compiler/rustc_data_structures/src/profiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,31 +94,34 @@ use std::process;
use std::sync::Arc;
use std::time::{Duration, Instant};

use measureme::{EventId, EventIdBuilder, Profiler, SerializableString, StringId};
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
use parking_lot::RwLock;

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 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 QUERY_KEYS = 1 << 5;
const FUNCTION_ARGS = 1 << 6;
const LLVM = 1 << 7;
const QUERY_KEYS = 1 << 5;
const FUNCTION_ARGS = 1 << 6;
const LLVM = 1 << 7;
const INCR_RESULT_HASHING = 1 << 8;

const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
Self::QUERY_PROVIDERS.bits |
Self::QUERY_BLOCKED.bits |
Self::INCR_CACHE_LOADS.bits;
Self::INCR_CACHE_LOADS.bits |
Self::INCR_RESULT_HASHING.bits;

const ARGS = Self::QUERY_KEYS.bits | Self::FUNCTION_ARGS.bits;
}
}

// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs
// keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs
const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
("none", EventFilter::empty()),
("all", EventFilter::all()),
Expand All @@ -132,6 +135,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
("function-args", EventFilter::FUNCTION_ARGS),
("args", EventFilter::ARGS),
("llvm", EventFilter::LLVM),
("incr-result-hashing", EventFilter::INCR_RESULT_HASHING),
];

/// Something that uniquely identifies a query invocation.
Expand Down Expand Up @@ -248,6 +252,15 @@ impl SelfProfilerRef {
})
}

/// Start profiling with some event filter for a given event. Profiling continues until the
/// TimingGuard returned from this call is dropped.
#[inline(always)]
pub fn generic_activity_with_event_id(&self, event_id: EventId) -> TimingGuard<'_> {
self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
})
}

/// Start profiling a generic activity. Profiling continues until the
/// TimingGuard returned from this call is dropped.
#[inline(always)]
Expand Down Expand Up @@ -337,6 +350,19 @@ impl SelfProfilerRef {
})
}

/// Start profiling how long it takes to hash query results for incremental compilation.
/// Profiling continues until the TimingGuard returned from this call is dropped.
#[inline(always)]
pub fn incr_result_hashing(&self) -> TimingGuard<'_> {
self.exec(EventFilter::INCR_RESULT_HASHING, |profiler| {
TimingGuard::start(
profiler,
profiler.incremental_result_hashing_event_kind,
EventId::INVALID,
)
})
}

#[inline(always)]
fn instant_query_event(
&self,
Expand Down Expand Up @@ -364,6 +390,14 @@ impl SelfProfilerRef {
}
}

/// Gets a `StringId` for the given string. This method makes sure that
/// any strings going through it will only be allocated once in the
/// profiling data.
/// Returns `None` if the self-profiling is not enabled.
pub fn get_or_alloc_cached_string(&self, s: &str) -> Option<StringId> {
self.profiler.as_ref().map(|p| p.get_or_alloc_cached_string(s))
}

#[inline]
pub fn enabled(&self) -> bool {
self.profiler.is_some()
Expand All @@ -388,6 +422,7 @@ pub struct SelfProfiler {
query_event_kind: StringId,
generic_activity_event_kind: StringId,
incremental_load_result_event_kind: StringId,
incremental_result_hashing_event_kind: StringId,
query_blocked_event_kind: StringId,
query_cache_hit_event_kind: StringId,
}
Expand All @@ -408,6 +443,8 @@ impl SelfProfiler {
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 incremental_result_hashing_event_kind =
profiler.alloc_string("IncrementalResultHashing");
let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit");

Expand Down Expand Up @@ -451,6 +488,7 @@ impl SelfProfiler {
query_event_kind,
generic_activity_event_kind,
incremental_load_result_event_kind,
incremental_result_hashing_event_kind,
query_blocked_event_kind,
query_cache_hit_event_kind,
})
Expand Down
28 changes: 25 additions & 3 deletions compiler/rustc_query_system/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::QueryInvocationId;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef};
use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
Expand Down Expand Up @@ -36,6 +35,12 @@ pub struct DepGraph<K: DepKind> {
/// each task has a `DepNodeIndex` that uniquely identifies it. This unique
/// ID is used for self-profiling.
virtual_dep_node_index: Lrc<AtomicU32>,

/// The cached event id for profiling node interning. This saves us
/// from having to look up the event id every time we intern a node
/// which may incur too much overhead.
/// This will be None if self-profiling is disabled.
node_intern_event_id: Option<EventId>,
}

rustc_index::newtype_index! {
Expand Down Expand Up @@ -130,6 +135,10 @@ impl<K: DepKind> DepGraph<K> {
);
debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);

let node_intern_event_id = profiler
.get_or_alloc_cached_string("incr_comp_intern_dep_graph_node")
.map(EventId::from_label);

DepGraph {
data: Some(Lrc::new(DepGraphData {
previous_work_products: prev_work_products,
Expand All @@ -141,11 +150,16 @@ impl<K: DepKind> DepGraph<K> {
colors: DepNodeColorMap::new(prev_graph_node_count),
})),
virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
node_intern_event_id,
}
}

pub fn new_disabled() -> DepGraph<K> {
DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
DepGraph {
data: None,
virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
node_intern_event_id: None,
}
}

/// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
Expand Down Expand Up @@ -244,10 +258,15 @@ impl<K: DepKind> DepGraph<K> {
let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);

let mut hcx = dcx.create_stable_hashing_context();
let hashing_timer = dcx.profiler().incr_result_hashing();
let current_fingerprint = hash_result(&mut hcx, &result);

let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;

// Get timer for profiling `DepNode` interning
let node_intern_timer = self
.node_intern_event_id
.map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
// Intern the new `DepNode`.
let (dep_node_index, prev_and_color) = data.current.intern_node(
dcx.profiler(),
Expand All @@ -257,6 +276,9 @@ impl<K: DepKind> DepGraph<K> {
current_fingerprint,
print_status,
);
drop(node_intern_timer);

hashing_timer.finish_with_query_invocation_id(dep_node_index.into());

if let Some((prev_index, color)) = prev_and_color {
debug_assert!(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,7 @@ options! {
"specify the events recorded by the self profiler;
for example: `-Z self-profile-events=default,query-keys`
all options: none, all, default, generic-activity, query-provider, query-cache-hit
query-blocked, incr-cache-load, query-keys, function-args, args, llvm"),
query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm"),
share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make the current crate share its generic instantiations"),
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
Expand Down