Skip to content

Commit daffa9b

Browse files
committed
refactor(timings): enum instead of string for section name
So that we ensure that we always pass lower case to JavaScript
1 parent bf26a0a commit daffa9b

File tree

2 files changed

+66
-54
lines changed

2 files changed

+66
-54
lines changed

src/cargo/core/compiler/timings/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ struct UnitData {
135135
rmeta_time: Option<f64>,
136136
unblocked_units: Vec<usize>,
137137
unblocked_rmeta_units: Vec<usize>,
138-
sections: Option<Vec<(String, report::SectionData)>>,
138+
sections: Option<Vec<(report::SectionName, report::SectionData)>>,
139139
}
140140

141141
impl<'gctx> Timings<'gctx> {

src/cargo/core/compiler/timings/report.rs

Lines changed: 65 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Render HTML report from timing tracking data.
22
3+
use std::borrow::Cow;
34
use std::collections::HashMap;
45
use std::io::Write;
56
use std::time::Instant;
@@ -14,13 +15,10 @@ use super::Concurrency;
1415
use super::UnitData;
1516
use super::UnitTime;
1617

17-
const FRONTEND_SECTION_NAME: &str = "Frontend";
18-
const CODEGEN_SECTION_NAME: &str = "Codegen";
19-
2018
/// Contains post-processed data of individual compilation sections.
2119
enum AggregatedSections {
2220
/// We know the names and durations of individual compilation sections
23-
Sections(Vec<(String, SectionData)>),
21+
Sections(Vec<(SectionName, SectionData)>),
2422
/// We only know when .rmeta was generated, so we can distill frontend and codegen time.
2523
OnlyMetadataTime {
2624
frontend: SectionData,
@@ -30,6 +28,50 @@ enum AggregatedSections {
3028
OnlyTotalDuration,
3129
}
3230

31+
/// Name of an individual compilation section.
32+
#[derive(Clone, Hash, Eq, PartialEq)]
33+
pub(super) enum SectionName {
34+
Frontend,
35+
Codegen,
36+
Named(String),
37+
Other,
38+
}
39+
40+
impl SectionName {
41+
/// Lower case name.
42+
fn name(&self) -> Cow<'static, str> {
43+
match self {
44+
SectionName::Frontend => "frontend".into(),
45+
SectionName::Codegen => "codegen".into(),
46+
SectionName::Named(n) => n.to_lowercase().into(),
47+
SectionName::Other => "other".into(),
48+
}
49+
}
50+
51+
fn capitalized_name(&self) -> String {
52+
// Make the first "letter" uppercase. We could probably just assume ASCII here, but this
53+
// should be Unicode compatible.
54+
fn capitalize(s: &str) -> String {
55+
let first_char = s
56+
.chars()
57+
.next()
58+
.map(|c| c.to_uppercase().to_string())
59+
.unwrap_or_default();
60+
format!("{first_char}{}", s.chars().skip(1).collect::<String>())
61+
}
62+
capitalize(&self.name())
63+
}
64+
}
65+
66+
impl serde::ser::Serialize for SectionName {
67+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68+
where
69+
S: serde::Serializer,
70+
{
71+
self.name().serialize(serializer)
72+
}
73+
}
74+
3375
/// Postprocessed section data that has both start and an end.
3476
#[derive(Copy, Clone, serde::Serialize)]
3577
pub(super) struct SectionData {
@@ -225,51 +267,23 @@ fn write_unit_table(ctx: &RenderContext<'_>, f: &mut impl Write) -> CargoResult<
225267
let mut units: Vec<&UnitTime> = ctx.unit_times.iter().collect();
226268
units.sort_unstable_by(|a, b| b.duration.partial_cmp(&a.duration).unwrap());
227269

228-
// Make the first "letter" uppercase. We could probably just assume ASCII here, but this
229-
// should be Unicode compatible.
230-
fn capitalize(s: &str) -> String {
231-
let first_char = s
232-
.chars()
233-
.next()
234-
.map(|c| c.to_uppercase().to_string())
235-
.unwrap_or_default();
236-
format!("{first_char}{}", s.chars().skip(1).collect::<String>())
237-
}
238-
239270
// We can have a bunch of situations here.
240271
// - -Zsection-timings is enabled, and we received some custom sections, in which
241272
// case we use them to determine the headers.
242273
// - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.
243274
// - We only have total durations, so we don't add any additional headers.
244-
let aggregated: Vec<AggregatedSections> = units
245-
.iter()
246-
.map(|u|
247-
// Normalize the section names so that they are capitalized, so that we can later
248-
// refer to them with the capitalized name both when computing headers and when
249-
// looking up cells.
250-
match aggregate_sections(u) {
251-
AggregatedSections::Sections(sections) => AggregatedSections::Sections(
252-
sections.into_iter()
253-
.map(|(name, data)| (capitalize(&name), data))
254-
.collect()
255-
),
256-
s => s
257-
})
258-
.collect();
275+
let aggregated: Vec<AggregatedSections> = units.iter().map(|u| aggregate_sections(u)).collect();
259276

260-
let headers: Vec<String> = if let Some(sections) = aggregated.iter().find_map(|s| match s {
277+
let headers: Vec<_> = if let Some(sections) = aggregated.iter().find_map(|s| match s {
261278
AggregatedSections::Sections(sections) => Some(sections),
262279
_ => None,
263280
}) {
264-
sections.into_iter().map(|s| s.0.clone()).collect()
281+
sections.iter().map(|s| s.0.clone()).collect()
265282
} else if aggregated
266283
.iter()
267284
.any(|s| matches!(s, AggregatedSections::OnlyMetadataTime { .. }))
268285
{
269-
vec![
270-
FRONTEND_SECTION_NAME.to_string(),
271-
CODEGEN_SECTION_NAME.to_string(),
272-
]
286+
vec![SectionName::Frontend, SectionName::Codegen]
273287
} else {
274288
vec![]
275289
};
@@ -289,11 +303,14 @@ fn write_unit_table(ctx: &RenderContext<'_>, f: &mut impl Write) -> CargoResult<
289303
</thead>
290304
<tbody>
291305
"#,
292-
headers = headers.iter().map(|h| format!("<th>{h}</th>")).join("\n")
306+
headers = headers
307+
.iter()
308+
.map(|h| format!("<th>{}</th>", h.capitalized_name()))
309+
.join("\n")
293310
)?;
294311

295312
for (i, (unit, aggregated_sections)) in units.iter().zip(aggregated).enumerate() {
296-
let format_duration = |section: Option<SectionData>| match section {
313+
let format_duration = |section: Option<&SectionData>| match section {
297314
Some(section) => {
298315
let duration = section.duration();
299316
let pct = (duration / unit.duration) * 100.0;
@@ -306,28 +323,23 @@ fn write_unit_table(ctx: &RenderContext<'_>, f: &mut impl Write) -> CargoResult<
306323
// arbitrary set of headers, and an arbitrary set of sections per unit, so we always
307324
// initiate the cells to be empty, and then try to find a corresponding column for which
308325
// we might have data.
309-
let mut cells: HashMap<&str, SectionData> = Default::default();
326+
let mut cells = HashMap::new();
310327

311328
match &aggregated_sections {
312329
AggregatedSections::Sections(sections) => {
313330
for (name, data) in sections {
314-
cells.insert(&name, *data);
331+
cells.insert(name, data);
315332
}
316333
}
317334
AggregatedSections::OnlyMetadataTime { frontend, codegen } => {
318-
cells.insert(FRONTEND_SECTION_NAME, *frontend);
319-
cells.insert(CODEGEN_SECTION_NAME, *codegen);
335+
cells.insert(&SectionName::Frontend, frontend);
336+
cells.insert(&SectionName::Codegen, codegen);
320337
}
321338
AggregatedSections::OnlyTotalDuration => {}
322339
};
323340
let cells = headers
324341
.iter()
325-
.map(|header| {
326-
format!(
327-
"<td>{}</td>",
328-
format_duration(cells.remove(header.as_str()))
329-
)
330-
})
342+
.map(|header| format!("<td>{}</td>", format_duration(cells.remove(header))))
331343
.join("\n");
332344

333345
let features = unit.unit.features.join(", ");
@@ -396,7 +408,7 @@ fn to_unit_data(unit_times: &[UnitTime]) -> Vec<UnitData> {
396408
&& section.end < ut.duration
397409
{
398410
sections.push((
399-
"other".to_string(),
411+
SectionName::Other,
400412
SectionData {
401413
start: section.end,
402414
end: ut.duration,
@@ -442,7 +454,7 @@ fn aggregate_sections(unit_time: &UnitTime) -> AggregatedSections {
442454
// The frontend section is currently implicit in rustc, it is assumed to start at
443455
// compilation start and end when codegen starts. So we hard-code it here.
444456
let mut previous_section = (
445-
FRONTEND_SECTION_NAME.to_string(),
457+
SectionName::Frontend,
446458
CompilationSection {
447459
start: 0.0,
448460
end: None,
@@ -452,18 +464,18 @@ fn aggregate_sections(unit_time: &UnitTime) -> AggregatedSections {
452464
// Store the previous section, potentially setting its end to the start of the
453465
// current section.
454466
sections.push((
455-
previous_section.0.clone(),
467+
previous_section.0,
456468
SectionData {
457469
start: previous_section.1.start,
458470
end: previous_section.1.end.unwrap_or(section.start),
459471
},
460472
));
461-
previous_section = (name, section);
473+
previous_section = (SectionName::Named(name), section);
462474
}
463475
// Store the last section, potentially setting its end to the end of the whole
464476
// compilation.
465477
sections.push((
466-
previous_section.0.clone(),
478+
previous_section.0,
467479
SectionData {
468480
start: previous_section.1.start,
469481
end: previous_section.1.end.unwrap_or(end),

0 commit comments

Comments
 (0)