Skip to content

Commit 199e9e7

Browse files
committed
Add compilation sections to the HTML unit table
1 parent 5224b47 commit 199e9e7

File tree

1 file changed

+80
-4
lines changed

1 file changed

+80
-4
lines changed

src/cargo/core/compiler/timings.rs

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,47 @@ impl UnitTime {
105105
fn aggregate_sections(&self) -> AggregatedSections {
106106
let end = self.duration;
107107

108-
if let Some(rmeta) = self.rmeta_time {
108+
if !self.sections.is_empty() {
109+
// We have some detailed compilation section timings, so we postprocess them
110+
// Since it is possible that we do not have an end timestamp for a given compilation
111+
// section, we need to iterate them and if an end is missing, we assign the end of
112+
// the section to the start of the following section.
113+
114+
let mut sections = vec![];
115+
116+
// The frontend section is currently implicit in rustc, it is assumed to start at
117+
// compilation start and end when codegen starts. So we hard-code it here.
118+
let mut previous_section = (
119+
FRONTEND_SECTION_NAME.to_string(),
120+
CompilationSection {
121+
start: 0.0,
122+
end: None,
123+
},
124+
);
125+
for (name, section) in self.sections.clone() {
126+
// Store the previous section, potentially setting its end to the start of the
127+
// current section.
128+
sections.push((
129+
previous_section.0.clone(),
130+
SectionData {
131+
start: previous_section.1.start,
132+
end: previous_section.1.end.unwrap_or(section.start),
133+
},
134+
));
135+
previous_section = (name, section);
136+
}
137+
// Store the last section, potentially setting its end to the end of the whole
138+
// compilation.
139+
sections.push((
140+
previous_section.0.clone(),
141+
SectionData {
142+
start: previous_section.1.start,
143+
end: previous_section.1.end.unwrap_or(end),
144+
},
145+
));
146+
147+
AggregatedSections::Sections(sections)
148+
} else if let Some(rmeta) = self.rmeta_time {
109149
// We only know when the rmeta time was generated
110150
AggregatedSections::OnlyMetadataTime {
111151
frontend: SectionData {
@@ -153,6 +193,8 @@ impl SectionData {
153193
/// Contains post-processed data of individual compilation sections.
154194
#[derive(serde::Serialize)]
155195
enum AggregatedSections {
196+
/// We know the names and durations of individual compilation sections
197+
Sections(Vec<(String, SectionData)>),
156198
/// We only know when .rmeta was generated, so we can distill frontend and codegen time.
157199
OnlyMetadataTime {
158200
frontend: SectionData,
@@ -609,15 +651,44 @@ impl<'gctx> Timings<'gctx> {
609651
let mut units: Vec<&UnitTime> = self.unit_times.iter().collect();
610652
units.sort_unstable_by(|a, b| b.duration.partial_cmp(&a.duration).unwrap());
611653

654+
// Make the first "letter" uppercase. We could probably just assume ASCII here, but this
655+
// should be Unicode compatible.
656+
fn capitalize(s: &str) -> String {
657+
let first_char = s
658+
.chars()
659+
.next()
660+
.map(|c| c.to_uppercase().to_string())
661+
.unwrap_or_default();
662+
format!("{first_char}{}", s.chars().skip(1).collect::<String>())
663+
}
664+
612665
// We can have a bunch of situations here.
613666
// - -Zsection-timings is enabled, and we received some custom sections, in which
614667
// case we use them to determine the headers.
615668
// - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.
616669
// - We only have total durations, so we don't add any additional headers.
617-
let aggregated: Vec<AggregatedSections> =
618-
units.iter().map(|u| u.aggregate_sections()).collect();
670+
let aggregated: Vec<AggregatedSections> = units
671+
.iter()
672+
.map(|u|
673+
// Normalize the section names so that they are capitalized, so that we can later
674+
// refer to them with the capitalized name both when computing headers and when
675+
// looking up cells.
676+
match u.aggregate_sections() {
677+
AggregatedSections::Sections(sections) => AggregatedSections::Sections(
678+
sections.into_iter()
679+
.map(|(name, data)| (capitalize(&name), data))
680+
.collect()
681+
),
682+
s => s
683+
})
684+
.collect();
619685

620-
let headers: Vec<String> = if aggregated
686+
let headers: Vec<String> = if let Some(sections) = aggregated.iter().find_map(|s| match s {
687+
AggregatedSections::Sections(sections) => Some(sections),
688+
_ => None,
689+
}) {
690+
sections.into_iter().map(|s| s.0.clone()).collect()
691+
} else if aggregated
621692
.iter()
622693
.any(|s| matches!(s, AggregatedSections::OnlyMetadataTime { .. }))
623694
{
@@ -664,6 +735,11 @@ impl<'gctx> Timings<'gctx> {
664735
let mut cells: HashMap<&str, SectionData> = Default::default();
665736

666737
match &aggregated_sections {
738+
AggregatedSections::Sections(sections) => {
739+
for (name, data) in sections {
740+
cells.insert(&name, *data);
741+
}
742+
}
667743
AggregatedSections::OnlyMetadataTime { frontend, codegen } => {
668744
cells.insert(FRONTEND_SECTION_NAME, *frontend);
669745
cells.insert(CODEGEN_SECTION_NAME, *codegen);

0 commit comments

Comments
 (0)