summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_data_structures/src/profiling.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_data_structures/src/profiling.rs')
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs105
1 files changed, 77 insertions, 28 deletions
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 443316836..1ed584eaf 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -97,6 +97,7 @@ use std::time::{Duration, Instant};
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
use parking_lot::RwLock;
+use serde_json::json;
use smallvec::SmallVec;
bitflags::bitflags! {
@@ -145,6 +146,15 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
/// Something that uniquely identifies a query invocation.
pub struct QueryInvocationId(pub u32);
+/// Which format to use for `-Z time-passes`
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum TimePassesFormat {
+ /// Emit human readable text
+ Text,
+ /// Emit structured JSON
+ Json,
+}
+
/// A reference to the SelfProfiler. It can be cloned and sent across thread
/// boundaries at will.
#[derive(Clone)]
@@ -158,14 +168,14 @@ pub struct SelfProfilerRef {
// actually enabled.
event_filter_mask: EventFilter,
- // Print verbose generic activities to stderr?
- print_verbose_generic_activities: bool,
+ // Print verbose generic activities to stderr.
+ print_verbose_generic_activities: Option<TimePassesFormat>,
}
impl SelfProfilerRef {
pub fn new(
profiler: Option<Arc<SelfProfiler>>,
- print_verbose_generic_activities: bool,
+ print_verbose_generic_activities: Option<TimePassesFormat>,
) -> SelfProfilerRef {
// If there is no SelfProfiler then the filter mask is set to NONE,
// ensuring that nothing ever tries to actually access it.
@@ -207,9 +217,10 @@ impl SelfProfilerRef {
/// a measureme event, "verbose" generic activities also print a timing entry to
/// stderr if the compiler is invoked with -Ztime-passes.
pub fn verbose_generic_activity(&self, event_label: &'static str) -> VerboseTimingGuard<'_> {
- let message = self.print_verbose_generic_activities.then(|| event_label.to_owned());
+ let message_and_format =
+ self.print_verbose_generic_activities.map(|format| (event_label.to_owned(), format));
- VerboseTimingGuard::start(message, self.generic_activity(event_label))
+ VerboseTimingGuard::start(message_and_format, self.generic_activity(event_label))
}
/// Like `verbose_generic_activity`, but with an extra arg.
@@ -221,11 +232,14 @@ impl SelfProfilerRef {
where
A: Borrow<str> + Into<String>,
{
- let message = self
+ let message_and_format = self
.print_verbose_generic_activities
- .then(|| format!("{}({})", event_label, event_arg.borrow()));
+ .map(|format| (format!("{}({})", event_label, event_arg.borrow()), format));
- VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg))
+ VerboseTimingGuard::start(
+ message_and_format,
+ self.generic_activity_with_arg(event_label, event_arg),
+ )
}
/// Start profiling a generic activity. Profiling continues until the
@@ -703,17 +717,32 @@ impl<'a> TimingGuard<'a> {
}
}
+struct VerboseInfo {
+ start_time: Instant,
+ start_rss: Option<usize>,
+ message: String,
+ format: TimePassesFormat,
+}
+
#[must_use]
pub struct VerboseTimingGuard<'a> {
- start_and_message: Option<(Instant, Option<usize>, String)>,
+ info: Option<VerboseInfo>,
_guard: TimingGuard<'a>,
}
impl<'a> VerboseTimingGuard<'a> {
- pub fn start(message: Option<String>, _guard: TimingGuard<'a>) -> Self {
+ pub fn start(
+ message_and_format: Option<(String, TimePassesFormat)>,
+ _guard: TimingGuard<'a>,
+ ) -> Self {
VerboseTimingGuard {
_guard,
- start_and_message: message.map(|msg| (Instant::now(), get_resident_set_size(), msg)),
+ info: message_and_format.map(|(message, format)| VerboseInfo {
+ start_time: Instant::now(),
+ start_rss: get_resident_set_size(),
+ message,
+ format,
+ }),
}
}
@@ -726,10 +755,10 @@ impl<'a> VerboseTimingGuard<'a> {
impl Drop for VerboseTimingGuard<'_> {
fn drop(&mut self) {
- if let Some((start_time, start_rss, ref message)) = self.start_and_message {
+ if let Some(info) = &self.info {
let end_rss = get_resident_set_size();
- let dur = start_time.elapsed();
- print_time_passes_entry(message, dur, start_rss, end_rss);
+ let dur = info.start_time.elapsed();
+ print_time_passes_entry(&info.message, dur, info.start_rss, end_rss, info.format);
}
}
}
@@ -739,7 +768,22 @@ pub fn print_time_passes_entry(
dur: Duration,
start_rss: Option<usize>,
end_rss: Option<usize>,
+ format: TimePassesFormat,
) {
+ match format {
+ TimePassesFormat::Json => {
+ let json = json!({
+ "pass": what,
+ "time": dur.as_secs_f64(),
+ "rss_start": start_rss,
+ "rss_end": end_rss,
+ });
+ eprintln!("time: {json}");
+ return;
+ }
+ TimePassesFormat::Text => (),
+ }
+
// Print the pass if its duration is greater than 5 ms, or it changed the
// measured RSS.
let is_notable = || {
@@ -796,21 +840,26 @@ fn get_thread_id() -> u32 {
cfg_if! {
if #[cfg(windows)] {
pub fn get_resident_set_size() -> Option<usize> {
- use std::mem::{self, MaybeUninit};
- use winapi::shared::minwindef::DWORD;
- use winapi::um::processthreadsapi::GetCurrentProcess;
- use winapi::um::psapi::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS};
-
- let mut pmc = MaybeUninit::<PROCESS_MEMORY_COUNTERS>::uninit();
- match unsafe {
- GetProcessMemoryInfo(GetCurrentProcess(), pmc.as_mut_ptr(), mem::size_of_val(&pmc) as DWORD)
- } {
- 0 => None,
- _ => {
- let pmc = unsafe { pmc.assume_init() };
- Some(pmc.WorkingSetSize as usize)
- }
+ use std::mem;
+
+ use windows::{
+ Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
+ Win32::System::Threading::GetCurrentProcess,
+ };
+
+ let mut pmc = PROCESS_MEMORY_COUNTERS::default();
+ let pmc_size = mem::size_of_val(&pmc);
+ unsafe {
+ K32GetProcessMemoryInfo(
+ GetCurrentProcess(),
+ &mut pmc,
+ pmc_size as u32,
+ )
}
+ .ok()
+ .ok()?;
+
+ Some(pmc.WorkingSetSize)
}
} else if #[cfg(target_os = "macos")] {
pub fn get_resident_set_size() -> Option<usize> {