about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-06-23 12:48:20 -0700
committerGitHub <noreply@github.com>2025-06-23 12:48:20 -0700
commit8ba69d0f95fa75763fde16fce6cb6388326edf9d (patch)
treeab2f501c5b660d8681245c5153c673814bb6c4bf /compiler/rustc_errors/src
parentff1636b6e3fb685f43b17be8a12905203c8717da (diff)
parent332ae3b7e632eb23c39b9844f44e2f9e7409e622 (diff)
downloadrust-8ba69d0f95fa75763fde16fce6cb6388326edf9d.tar.gz
rust-8ba69d0f95fa75763fde16fce6cb6388326edf9d.zip
Rollup merge of #142784 - Kobzol:timings-codegen, r=nnethercote
Add codegen timing section

And since we now start and end the sections also using separate functions, also add some light checking if we're generating the sections correctly.

I'm integrating `--timings` into Cargo, and I realized that the codegen timings would be quite useful for that. Frontend can be computed simply as `[start of compilation, start of codegen]` for now.

r? `@nnethercote`
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/json.rs1
-rw-r--r--compiler/rustc_errors/src/timings.rs47
2 files changed, 45 insertions, 3 deletions
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 6d600f896a0..4348610be0a 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -129,6 +129,7 @@ impl Emitter for JsonEmitter {
         };
         let name = match record.section {
             TimingSection::Linking => "link",
+            TimingSection::Codegen => "codegen",
         };
         let data = SectionTimestamp { name, event, timestamp: record.timestamp };
         let result = self.emit(EmitTyped::SectionTiming(data));
diff --git a/compiler/rustc_errors/src/timings.rs b/compiler/rustc_errors/src/timings.rs
index 27fc9df8d79..0d82f3e8db8 100644
--- a/compiler/rustc_errors/src/timings.rs
+++ b/compiler/rustc_errors/src/timings.rs
@@ -1,10 +1,15 @@
 use std::time::Instant;
 
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lock;
+
 use crate::DiagCtxtHandle;
 
 /// A high-level section of the compilation process.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum TimingSection {
+    /// Time spent doing codegen.
+    Codegen,
     /// Time spent linking.
     Linking,
 }
@@ -36,23 +41,59 @@ pub struct TimingSectionHandler {
     /// Time when the compilation session started.
     /// If `None`, timing is disabled.
     origin: Option<Instant>,
+    /// Sanity check to ensure that we open and close sections correctly.
+    opened_sections: Lock<FxHashSet<TimingSection>>,
 }
 
 impl TimingSectionHandler {
     pub fn new(enabled: bool) -> Self {
         let origin = if enabled { Some(Instant::now()) } else { None };
-        Self { origin }
+        Self { origin, opened_sections: Lock::new(FxHashSet::default()) }
     }
 
     /// Returns a RAII guard that will immediately emit a start the provided section, and then emit
     /// its end when it is dropped.
-    pub fn start_section<'a>(
+    pub fn section_guard<'a>(
         &self,
         diag_ctxt: DiagCtxtHandle<'a>,
         section: TimingSection,
     ) -> TimingSectionGuard<'a> {
+        if self.is_enabled() && self.opened_sections.borrow().contains(&section) {
+            diag_ctxt
+                .bug(format!("Section `{section:?}` was started again before it was finished"));
+        }
+
         TimingSectionGuard::create(diag_ctxt, section, self.origin)
     }
+
+    /// Start the provided section.
+    pub fn start_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) {
+        if let Some(origin) = self.origin {
+            let mut opened = self.opened_sections.borrow_mut();
+            if !opened.insert(section) {
+                diag_ctxt
+                    .bug(format!("Section `{section:?}` was started again before it was finished"));
+            }
+
+            diag_ctxt.emit_timing_section_start(TimingRecord::from_origin(origin, section));
+        }
+    }
+
+    /// End the provided section.
+    pub fn end_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) {
+        if let Some(origin) = self.origin {
+            let mut opened = self.opened_sections.borrow_mut();
+            if !opened.remove(&section) {
+                diag_ctxt.bug(format!("Section `{section:?}` was ended before being started"));
+            }
+
+            diag_ctxt.emit_timing_section_end(TimingRecord::from_origin(origin, section));
+        }
+    }
+
+    fn is_enabled(&self) -> bool {
+        self.origin.is_some()
+    }
 }
 
 /// RAII wrapper for starting and ending section timings.