Skip to content

Commit b113819

Browse files
committed
Render section timing data in the unit table
1 parent 1c5aaec commit b113819

File tree

1 file changed

+121
-14
lines changed

1 file changed

+121
-14
lines changed

src/cargo/core/compiler/timings.rs

Lines changed: 121 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,50 @@ struct UnitTime {
9292
sections: HashMap<String, TimingSection>,
9393
}
9494

95+
impl UnitTime {
96+
fn aggregate_sections(&self) -> AggregatedSections {
97+
let end = self.duration;
98+
99+
let codegen_section = self.sections.get("codegen");
100+
let link_section = self.sections.get("link");
101+
102+
// Best case: we know all three sections
103+
if let (Some(codegen_section), Some(link_section)) = (codegen_section, link_section) {
104+
let link_start = link_section.start;
105+
let codegen_end = codegen_section.end.unwrap_or(link_start);
106+
107+
AggregatedSections::Sections {
108+
frontend: SectionData {
109+
start: 0.0,
110+
end: codegen_section.start,
111+
},
112+
codegen: SectionData {
113+
start: codegen_section.start,
114+
end: codegen_end,
115+
},
116+
linking: SectionData {
117+
start: link_start,
118+
end: link_section.end.unwrap_or(end),
119+
},
120+
}
121+
} else if let Some(rmeta_time) = self.rmeta_time {
122+
// We know at least the .rmeta time
123+
AggregatedSections::OnlyCodegenDuration {
124+
frontend: SectionData {
125+
start: 0.0,
126+
end: rmeta_time,
127+
},
128+
codegen: SectionData {
129+
start: rmeta_time,
130+
end,
131+
},
132+
}
133+
} else {
134+
AggregatedSections::OnlyTotalDuration
135+
}
136+
}
137+
}
138+
95139
/// Periodic concurrency tracking information.
96140
#[derive(serde::Serialize)]
97141
struct Concurrency {
@@ -106,6 +150,39 @@ struct Concurrency {
106150
inactive: usize,
107151
}
108152

153+
/// Postprocessed section data that has both start and an end.
154+
#[derive(serde::Serialize)]
155+
struct SectionData {
156+
/// Start (relative to the start of the unit)
157+
start: f64,
158+
/// End (relative to the start of the unit)
159+
end: f64,
160+
}
161+
162+
impl SectionData {
163+
fn duration(&self) -> f64 {
164+
(self.end - self.start).max(0.0)
165+
}
166+
}
167+
168+
/// Contains post-processed data of individual compilation sections.
169+
#[derive(serde::Serialize)]
170+
enum AggregatedSections {
171+
/// We know only the total duration
172+
OnlyTotalDuration,
173+
/// We only know when .rmeta was generated, so we can distill frontend and codegen time.
174+
OnlyCodegenDuration {
175+
frontend: SectionData,
176+
codegen: SectionData,
177+
},
178+
/// We know the durations of the three individual sections.
179+
Sections {
180+
frontend: SectionData,
181+
codegen: SectionData,
182+
linking: SectionData,
183+
},
184+
}
185+
109186
impl<'gctx> Timings<'gctx> {
110187
pub fn new(bcx: &BuildContext<'_, 'gctx>, root_units: &[Unit]) -> Timings<'gctx> {
111188
let has_report = |what| bcx.build_config.timing_outputs.contains(&what);
@@ -476,6 +553,7 @@ impl<'gctx> Timings<'gctx> {
476553
.enumerate()
477554
.map(|(i, ut)| (ut.unit.clone(), i))
478555
.collect();
556+
479557
#[derive(serde::Serialize)]
480558
struct UnitData {
481559
i: usize,
@@ -549,6 +627,18 @@ impl<'gctx> Timings<'gctx> {
549627

550628
/// Render the table of all units.
551629
fn write_unit_table(&self, f: &mut impl Write) -> CargoResult<()> {
630+
let mut units: Vec<&UnitTime> = self.unit_times.iter().collect();
631+
units.sort_unstable_by(|a, b| b.duration.partial_cmp(&a.duration).unwrap());
632+
633+
let has_linking_time = units
634+
.iter()
635+
.any(|u| matches!(u.aggregate_sections(), AggregatedSections::Sections { .. }));
636+
// Skip the linker column if we have no data for it
637+
let linking_header = if has_linking_time {
638+
"<th>Linking</th>"
639+
} else {
640+
""
641+
};
552642
write!(
553643
f,
554644
r#"
@@ -558,20 +648,38 @@ impl<'gctx> Timings<'gctx> {
558648
<th></th>
559649
<th>Unit</th>
560650
<th>Total</th>
651+
<th>Frontend</th>
561652
<th>Codegen</th>
653+
{linking_header}
562654
<th>Features</th>
563655
</tr>
564656
</thead>
565657
<tbody>
566658
"#
567659
)?;
568-
let mut units: Vec<&UnitTime> = self.unit_times.iter().collect();
569-
units.sort_unstable_by(|a, b| b.duration.partial_cmp(&a.duration).unwrap());
660+
570661
for (i, unit) in units.iter().enumerate() {
571-
let codegen = match unit.codegen_time() {
662+
let format_duration = |section: Option<SectionData>| match section {
663+
Some(section) => {
664+
let duration = section.duration();
665+
let pct = (duration / unit.duration) * 100.0;
666+
format!("{duration:.1}s ({:.0}%)", pct)
667+
}
572668
None => "".to_string(),
573-
Some((_rt, ctime, cent)) => format!("{:.1}s ({:.0}%)", ctime, cent),
574669
};
670+
let sections = unit.aggregate_sections();
671+
let (frontend, codegen, linking) = match sections {
672+
AggregatedSections::OnlyTotalDuration => (None, None, None),
673+
AggregatedSections::OnlyCodegenDuration { frontend, codegen } => {
674+
(Some(frontend), Some(codegen), None)
675+
}
676+
AggregatedSections::Sections {
677+
frontend,
678+
codegen,
679+
linking,
680+
} => (Some(frontend), Some(codegen), Some(linking)),
681+
};
682+
575683
let features = unit.unit.features.join(", ");
576684
write!(
577685
f,
@@ -582,13 +690,21 @@ impl<'gctx> Timings<'gctx> {
582690
<td>{:.1}s</td>
583691
<td>{}</td>
584692
<td>{}</td>
693+
{}
694+
<td>{}</td>
585695
</tr>
586696
"#,
587697
i + 1,
588698
unit.name_ver(),
589699
unit.target,
590700
unit.duration,
591-
codegen,
701+
format_duration(frontend),
702+
format_duration(codegen),
703+
if has_linking_time {
704+
format!("<td>{}</td>", format_duration(linking))
705+
} else {
706+
"".to_string()
707+
},
592708
features,
593709
)?;
594710
}
@@ -598,15 +714,6 @@ impl<'gctx> Timings<'gctx> {
598714
}
599715

600716
impl UnitTime {
601-
/// Returns the codegen time as (`rmeta_time`, `codegen_time`, percent of total)
602-
fn codegen_time(&self) -> Option<(f64, f64, f64)> {
603-
self.rmeta_time.map(|rmeta_time| {
604-
let ctime = self.duration - rmeta_time;
605-
let cent = (ctime / self.duration) * 100.0;
606-
(rmeta_time, ctime, cent)
607-
})
608-
}
609-
610717
fn name_ver(&self) -> String {
611718
format!("{} v{}", self.unit.pkg.name(), self.unit.pkg.version())
612719
}

0 commit comments

Comments
 (0)