From d76573abd19d50c25c5b58ec7fc5cfef579e6eef Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 22 Oct 2020 08:51:31 +0300 Subject: [PATCH 1/9] Integrate measureme's hardware performance counter support. --- compiler/rustc_data_structures/src/profiling.rs | 14 ++++++++++---- compiler/rustc_query_impl/src/profiling_support.rs | 3 +++ compiler/rustc_session/src/options.rs | 6 ++++++ compiler/rustc_session/src/session.rs | 3 ++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index bf7924a81fffc..a1f42d8d3c059 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -550,14 +550,20 @@ impl SelfProfiler { pub fn new( output_directory: &Path, crate_name: Option<&str>, - event_filters: &Option>, + event_filters: Option<&[String]>, + counter_name: &str, ) -> Result> { fs::create_dir_all(output_directory)?; let crate_name = crate_name.unwrap_or("unknown-crate"); - let filename = format!("{}-{}.rustc_profile", crate_name, process::id()); + // HACK(eddyb) we need to pad the PID, strange as it may seem, as its + // length can behave as a source of entropy for heap addresses, when + // ASLR is disabled and the heap is otherwise determinic. + let pid: u32 = process::id(); + let filename = format!("{}-{:07}.rustc_profile", crate_name, pid); let path = output_directory.join(&filename); - let profiler = Profiler::new(&path)?; + let profiler = + Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?; let query_event_kind = profiler.alloc_string("Query"); let generic_activity_event_kind = profiler.alloc_string("GenericActivity"); @@ -570,7 +576,7 @@ impl SelfProfiler { let mut event_filter_mask = EventFilter::empty(); - if let Some(ref event_filters) = *event_filters { + if let Some(event_filters) = event_filters { let mut unknown_events = vec![]; for item in event_filters { if let Some(&(_, mask)) = diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index b20aa7b53468a..551f094209e4e 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -275,6 +275,9 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( let query_name = profiler.get_or_alloc_cached_string(query_name); let event_id = event_id_builder.from_label(query_name).to_string_id(); + // FIXME(eddyb) make this O(1) by using a pre-cached query name `EventId`, + // instead of passing the `DepNodeIndex` to `finish_with_query_invocation_id`, + // when recording the event in the first place. let mut query_invocation_ids = Vec::new(); query_cache.iter(&mut |_, _, i| { query_invocation_ids.push(i.into()); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 007fa87189fb0..64c8274abdfcc 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1473,6 +1473,12 @@ options! { 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, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"), + self_profile_counter: String = ("wall-time".to_string(), parse_string, [UNTRACKED], + "counter used by the self profiler (default: `wall-time`), one of: + `wall-time` (monotonic clock, i.e. `std::time::Instant`) + `instructions:u` (retired instructions, userspace-only) + `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)" + ), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), show_span: Option = (None, parse_opt_string, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b2c23cda6aae5..f74de55ad7b99 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1252,7 +1252,8 @@ pub fn build_session( let profiler = SelfProfiler::new( directory, sopts.crate_name.as_deref(), - &sopts.debugging_opts.self_profile_events, + sopts.debugging_opts.self_profile_events.as_ref().map(|xs| &xs[..]), + &sopts.debugging_opts.self_profile_counter, ); match profiler { Ok(profiler) => Some(Arc::new(profiler)), From 07c7ba72056cf03830dc508ad634b9c371cd4a89 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Nov 2020 19:29:40 +0200 Subject: [PATCH 2/9] proc_macro: bypass RandomState to remove ASLR-like effects. --- library/proc_macro/src/bridge/handle.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs index 7d6adda48ec6e..c219a9465d39f 100644 --- a/library/proc_macro/src/bridge/handle.rs +++ b/library/proc_macro/src/bridge/handle.rs @@ -1,7 +1,7 @@ //! Server-side handles and storage for per-handle data. use std::collections::{BTreeMap, HashMap}; -use std::hash::Hash; +use std::hash::{BuildHasher, Hash}; use std::num::NonZeroU32; use std::ops::{Index, IndexMut}; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -51,15 +51,31 @@ impl IndexMut for OwnedStore { } } +// HACK(eddyb) deterministic `std::collections::hash_map::RandomState` replacement +// that doesn't require adding any dependencies to `proc_macro` (like `rustc-hash`). +#[derive(Clone)] +struct NonRandomState; + +impl BuildHasher for NonRandomState { + type Hasher = std::collections::hash_map::DefaultHasher; + #[inline] + fn build_hasher(&self) -> Self::Hasher { + Self::Hasher::new() + } +} + /// Like `OwnedStore`, but avoids storing any value more than once. pub(super) struct InternedStore { owned: OwnedStore, - interner: HashMap, + interner: HashMap, } impl InternedStore { pub(super) fn new(counter: &'static AtomicUsize) -> Self { - InternedStore { owned: OwnedStore::new(counter), interner: HashMap::new() } + InternedStore { + owned: OwnedStore::new(counter), + interner: HashMap::with_hasher(NonRandomState), + } } pub(super) fn alloc(&mut self, x: T) -> Handle { From a10f0d2c5d022bbc212b4dae08f88c79b91c744e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Nov 2020 19:29:14 +0200 Subject: [PATCH 3/9] rustc: disable jemalloc's time-delayed purging to remove ASLR-like effects. --- compiler/rustc/src/main.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 0de1a78191353..8d6f9b394ee4e 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -56,6 +56,12 @@ fn main() { #[used] static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; } + + // HACK(eddyb) disable time-delayed purging to remove the main (only?) + // source of non-determinism in `jemalloc`. + #[used] + #[export_name = "malloc_conf"] + static MALLOC_CONF: &'static [u8; 34] = b"dirty_decay_ms:0,muzzy_decay_ms:0\0"; } rustc_driver::set_sigpipe_handler(); From 0763c7be93b4cd8f3540077ed430ef8b8e8265c3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Jun 2022 08:00:06 +0000 Subject: [PATCH 4/9] Revert "rustc: disable jemalloc's time-delayed purging to remove ASLR-like effects." This reverts commit a10f0d2c5d022bbc212b4dae08f88c79b91c744e. --- compiler/rustc/src/main.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 8d6f9b394ee4e..0de1a78191353 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -56,12 +56,6 @@ fn main() { #[used] static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; } - - // HACK(eddyb) disable time-delayed purging to remove the main (only?) - // source of non-determinism in `jemalloc`. - #[used] - #[export_name = "malloc_conf"] - static MALLOC_CONF: &'static [u8; 34] = b"dirty_decay_ms:0,muzzy_decay_ms:0\0"; } rustc_driver::set_sigpipe_handler(); From 521218ce88e12ed2960f619545cf22404cee8d1e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Nov 2020 19:28:17 +0200 Subject: [PATCH 5/9] rustc_parse: work around instruction-counting non-determinism. --- compiler/rustc_parse/src/lexer/mod.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index e9701ec2d7f45..f3b11e9b604bf 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -335,17 +335,15 @@ impl<'a> StringReader<'a> { comment_kind: CommentKind, doc_style: DocStyle, ) -> TokenKind { - if content.contains('\r') { - for (idx, _) in content.char_indices().filter(|&(_, c)| c == '\r') { - self.err_span_( - content_start + BytePos(idx as u32), - content_start + BytePos(idx as u32 + 1), - match comment_kind { - CommentKind::Line => "bare CR not allowed in doc-comment", - CommentKind::Block => "bare CR not allowed in block doc-comment", - }, - ); - } + for (idx, _) in content.match_indices('\r') { + self.err_span_( + content_start + BytePos(idx as u32), + content_start + BytePos(idx as u32 + 1), + match comment_kind { + CommentKind::Line => "bare CR not allowed in doc-comment", + CommentKind::Block => "bare CR not allowed in block doc-comment", + }, + ); } let attr_style = match doc_style { From 44783f1db0bd1076d825b2b681c4220bbf97bbec Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Jun 2022 08:04:27 +0000 Subject: [PATCH 6/9] Revert "rustc_parse: work around instruction-counting non-determinism." This reverts commit 521218ce88e12ed2960f619545cf22404cee8d1e. --- compiler/rustc_parse/src/lexer/mod.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f3b11e9b604bf..e9701ec2d7f45 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -335,15 +335,17 @@ impl<'a> StringReader<'a> { comment_kind: CommentKind, doc_style: DocStyle, ) -> TokenKind { - for (idx, _) in content.match_indices('\r') { - self.err_span_( - content_start + BytePos(idx as u32), - content_start + BytePos(idx as u32 + 1), - match comment_kind { - CommentKind::Line => "bare CR not allowed in doc-comment", - CommentKind::Block => "bare CR not allowed in block doc-comment", - }, - ); + if content.contains('\r') { + for (idx, _) in content.char_indices().filter(|&(_, c)| c == '\r') { + self.err_span_( + content_start + BytePos(idx as u32), + content_start + BytePos(idx as u32 + 1), + match comment_kind { + CommentKind::Line => "bare CR not allowed in doc-comment", + CommentKind::Block => "bare CR not allowed in block doc-comment", + }, + ); + } } let attr_style = match doc_style { From 85947f0fe26360c17ea877ae67cac7c092de9cfc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Nov 2020 19:28:36 +0200 Subject: [PATCH 7/9] rustc_trait_selection: work around instruction-counting non-determinism. --- compiler/rustc_trait_selection/src/traits/select/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a484b594418c2..60e13d9b8c3b1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1525,6 +1525,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { other: &EvaluatedCandidate<'tcx>, needs_infer: bool, ) -> bool { + // HACK(eddyb) remove instruction-counting noise from `-Z self-profile`. + #[cfg(target_arch = "x86_64")] + unsafe { + std::arch::asm!("mfence", options(nostack)); + } + if victim.candidate == other.candidate { return true; } From 303ab3465c9d791907afe9f069fb23057de28cb3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Jun 2022 08:06:22 +0000 Subject: [PATCH 8/9] Revert "rustc_trait_selection: work around instruction-counting non-determinism." This reverts commit 85947f0fe26360c17ea877ae67cac7c092de9cfc. --- compiler/rustc_trait_selection/src/traits/select/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 60e13d9b8c3b1..a484b594418c2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1525,12 +1525,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { other: &EvaluatedCandidate<'tcx>, needs_infer: bool, ) -> bool { - // HACK(eddyb) remove instruction-counting noise from `-Z self-profile`. - #[cfg(target_arch = "x86_64")] - unsafe { - std::arch::asm!("mfence", options(nostack)); - } - if victim.candidate == other.candidate { return true; } From a4f1331b9d351658dcdf676e1560a807992dcfa9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Jun 2022 18:33:02 +0000 Subject: [PATCH 9/9] [perf] std: add missing `#[inline]` to `DefaultHasher::{new,default}`. --- library/std/src/collections/hash/map.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 11ccdd9ea1cc5..d38fecc45b2fc 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3140,6 +3140,7 @@ impl DefaultHasher { /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` /// instances created through `new` or `default`. #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] + #[inline] #[allow(deprecated)] #[must_use] pub fn new() -> DefaultHasher { @@ -3153,6 +3154,7 @@ impl Default for DefaultHasher { /// See its documentation for more. /// /// [`new`]: DefaultHasher::new + #[inline] fn default() -> DefaultHasher { DefaultHasher::new() }