Skip to content

Commit 71a0df9

Browse files
committed
Add compilation sections to the HTML unit table
1 parent 33acc34 commit 71a0df9

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
@@ -104,7 +104,47 @@ impl UnitTime {
104104
fn aggregate_sections(&self) -> AggregatedSections {
105105
let end = self.duration;
106106

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