Skip to content

Commit 3c3232e

Browse files
committed
Move BuildStep and metric logging into build_helper
To share it between `citool` and `opt-dist`.
1 parent c82ce2e commit 3c3232e

File tree

2 files changed

+79
-70
lines changed

2 files changed

+79
-70
lines changed

src/build_helper/src/metrics.rs

+76
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::Duration;
2+
13
use serde_derive::{Deserialize, Serialize};
24

35
#[derive(Serialize, Deserialize)]
@@ -100,3 +102,77 @@ fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Err
100102
use serde::Deserialize as _;
101103
Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN))
102104
}
105+
106+
/// Represents a single bootstrap step, with the accumulated duration of all its children.
107+
#[derive(Clone, Debug)]
108+
pub struct BuildStep {
109+
pub r#type: String,
110+
pub children: Vec<BuildStep>,
111+
pub duration: Duration,
112+
}
113+
114+
impl BuildStep {
115+
pub fn from_invocation(invocation: &JsonInvocation) -> Self {
116+
fn parse(node: &JsonNode) -> Option<BuildStep> {
117+
match node {
118+
JsonNode::RustbuildStep {
119+
type_: kind,
120+
children,
121+
duration_excluding_children_sec,
122+
..
123+
} => {
124+
let children: Vec<_> = children.into_iter().filter_map(parse).collect();
125+
let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
126+
Some(BuildStep {
127+
r#type: kind.to_string(),
128+
children,
129+
duration: children_duration
130+
+ Duration::from_secs_f64(*duration_excluding_children_sec),
131+
})
132+
}
133+
JsonNode::TestSuite(_) => None,
134+
}
135+
}
136+
137+
let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
138+
let children: Vec<_> = invocation.children.iter().filter_map(parse).collect();
139+
Self { r#type: "total".to_string(), children, duration }
140+
}
141+
142+
pub fn find_all_by_type(&self, r#type: &str) -> Vec<&BuildStep> {
143+
let mut result = Vec::new();
144+
self.find_by_type(r#type, &mut result);
145+
result
146+
}
147+
fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a BuildStep>) {
148+
if self.r#type == r#type {
149+
result.push(self);
150+
}
151+
for child in &self.children {
152+
child.find_by_type(r#type, result);
153+
}
154+
}
155+
}
156+
157+
/// Writes build steps into a nice indented table.
158+
pub fn format_build_steps(root: &BuildStep) -> String {
159+
use std::fmt::Write;
160+
161+
let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
162+
163+
fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
164+
substeps.push((level, step));
165+
for child in &step.children {
166+
visit(child, level + 1, substeps);
167+
}
168+
}
169+
170+
visit(root, 0, &mut substeps);
171+
172+
let mut output = String::new();
173+
for (level, step) in substeps {
174+
let label = format!("{}{}", ".".repeat(level as usize), step.r#type);
175+
writeln!(output, "{label:<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
176+
}
177+
output
178+
}

src/tools/opt-dist/src/metrics.rs

+3-70
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,10 @@
11
use std::time::Duration;
22

3-
use build_helper::metrics::{JsonNode, JsonRoot};
3+
use build_helper::metrics::{BuildStep, JsonRoot, format_build_steps};
44
use camino::Utf8Path;
55

66
use crate::timer::TimerSection;
77

8-
#[derive(Clone, Debug)]
9-
pub struct BuildStep {
10-
r#type: String,
11-
children: Vec<BuildStep>,
12-
duration: Duration,
13-
}
14-
15-
impl BuildStep {
16-
pub fn find_all_by_type(&self, r#type: &str) -> Vec<&BuildStep> {
17-
let mut result = Vec::new();
18-
self.find_by_type(r#type, &mut result);
19-
result
20-
}
21-
fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a BuildStep>) {
22-
if self.r#type == r#type {
23-
result.push(self);
24-
}
25-
for child in &self.children {
26-
child.find_by_type(r#type, result);
27-
}
28-
}
29-
}
30-
318
/// Loads the metrics of the most recent bootstrap execution from a metrics.json file.
329
pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
3310
let content = std::fs::read(path.as_std_path())?;
@@ -37,30 +14,7 @@ pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
3714
.pop()
3815
.ok_or_else(|| anyhow::anyhow!("No bootstrap invocation found in metrics file"))?;
3916

40-
fn parse(node: JsonNode) -> Option<BuildStep> {
41-
match node {
42-
JsonNode::RustbuildStep {
43-
type_: kind,
44-
children,
45-
duration_excluding_children_sec,
46-
..
47-
} => {
48-
let children: Vec<_> = children.into_iter().filter_map(parse).collect();
49-
let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
50-
Some(BuildStep {
51-
r#type: kind.to_string(),
52-
children,
53-
duration: children_duration
54-
+ Duration::from_secs_f64(duration_excluding_children_sec),
55-
})
56-
}
57-
JsonNode::TestSuite(_) => None,
58-
}
59-
}
60-
61-
let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
62-
let children: Vec<_> = invocation.children.into_iter().filter_map(parse).collect();
63-
Ok(BuildStep { r#type: "root".to_string(), children, duration })
17+
Ok(BuildStep::from_invocation(&invocation))
6418
}
6519

6620
/// Logs the individual metrics in a table and add Rustc and LLVM durations to the passed
@@ -82,27 +36,6 @@ pub fn record_metrics(metrics: &BuildStep, timer: &mut TimerSection) {
8236
timer.add_duration("Rustc", rustc_duration);
8337
}
8438

85-
log_metrics(metrics);
86-
}
87-
88-
fn log_metrics(metrics: &BuildStep) {
89-
use std::fmt::Write;
90-
91-
let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
92-
93-
fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
94-
substeps.push((level, step));
95-
for child in &step.children {
96-
visit(child, level + 1, substeps);
97-
}
98-
}
99-
100-
visit(metrics, 0, &mut substeps);
101-
102-
let mut output = String::new();
103-
for (level, step) in substeps {
104-
let label = format!("{}{}", ".".repeat(level as usize), step.r#type);
105-
writeln!(output, "{label:<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
106-
}
39+
let output = format_build_steps(metrics);
10740
log::info!("Build step durations\n{output}");
10841
}

0 commit comments

Comments
 (0)