Skip to content

Commit 91a8fb4

Browse files
authored
Merge pull request #957 from tgnottingham/graph-total-bootstrap-time
Graph total bootstrap time
2 parents 1a5b259 + fa390f2 commit 91a8fb4

File tree

7 files changed

+138
-42
lines changed

7 files changed

+138
-42
lines changed

database/src/pool.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,22 @@ pub trait Connection: Send + Sync {
6767
krate: &str,
6868
value: Duration,
6969
);
70-
71-
async fn get_bootstrap(
70+
/// Returns vector of bootstrap build times for the given artifacts. The kth
71+
/// element is the minimum build time for the kth artifact in `aids`, across
72+
/// all collections for the artifact, or none if there is no bootstrap data
73+
/// for that artifact (for example, because the rustc benchmark wasn't
74+
/// executed for that artifact).
75+
async fn get_bootstrap(&self, aids: &[ArtifactIdNumber]) -> Vec<Option<Duration>>;
76+
/// Returns map from rustc crate name to vector of build times for that crate
77+
/// for the given artifacts. Within a crate's corresponding vector, the kth
78+
/// element is the minimum build time for the kth artifact in `aids`, across
79+
/// all collections for the artifact, or none if there is no data for that
80+
/// artifact / crate combination (for example, because that rustc crate
81+
/// wasn't present when building rustc with that artifact, or because the
82+
/// rustc benchmark wasn't executed for that artifact). A crate will not be
83+
/// included as a key in the map unless at least one artifact in `aids` has a
84+
/// build time for it.
85+
async fn get_bootstrap_by_crate(
7286
&self,
7387
aids: &[ArtifactIdNumber],
7488
) -> HashMap<String, Vec<Option<Duration>>>;

database/src/pool/postgres.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ impl<'a> Transaction for PostgresTransaction<'a> {
264264
pub struct CachedStatements {
265265
get_pstat: Statement,
266266
get_rustc_compilation: Statement,
267+
get_rustc_compilation_by_crate: Statement,
267268
insert_pstat: Statement,
268269
insert_rustc: Statement,
269270
get_self_profile_query: Statement,
@@ -356,6 +357,16 @@ impl PostgresConnection {
356357
.await
357358
.unwrap(),
358359
get_rustc_compilation: conn.prepare("
360+
select aid, min(total)
361+
from (
362+
select aid, sum(duration) as total
363+
from rustc_compilation
364+
where aid = any($1)
365+
group by cid
366+
)
367+
group by aid
368+
").await.unwrap(),
369+
get_rustc_compilation_by_crate: conn.prepare("
359370
select
360371
aid,
361372
crate,
@@ -1184,7 +1195,36 @@ where
11841195
.collect()
11851196
}
11861197

1187-
async fn get_bootstrap(
1198+
async fn get_bootstrap(&self, aids: &[ArtifactIdNumber]) -> Vec<Option<Duration>> {
1199+
let mut result = vec![None; aids.len()];
1200+
1201+
let aid_to_idx = aids
1202+
.iter()
1203+
.copied()
1204+
.enumerate()
1205+
.map(|(idx, v)| (v, idx))
1206+
.collect::<HashMap<ArtifactIdNumber, usize>>();
1207+
1208+
let rows = self
1209+
.conn()
1210+
.query(
1211+
&self.statements().get_rustc_compilation,
1212+
&[&aids.iter().map(|v| v.0 as i32).collect::<Vec<_>>()],
1213+
)
1214+
.await
1215+
.unwrap();
1216+
1217+
for row in rows {
1218+
let aid = ArtifactIdNumber(row.get::<_, i32>(0) as u32);
1219+
let min_duration = row.get::<_, i64>(1);
1220+
1221+
result[aid_to_idx[&aid]] = Some(Duration::from_nanos(min_duration as u64));
1222+
}
1223+
1224+
result
1225+
}
1226+
1227+
async fn get_bootstrap_by_crate(
11881228
&self,
11891229
aids: &[ArtifactIdNumber],
11901230
) -> HashMap<String, Vec<Option<Duration>>> {
@@ -1198,7 +1238,7 @@ where
11981238
let rows = self
11991239
.conn()
12001240
.query(
1201-
&self.statements().get_rustc_compilation,
1241+
&self.statements().get_rustc_compilation_by_crate,
12021242
&[&aids.iter().map(|v| v.0 as i32).collect::<Vec<_>>()],
12031243
)
12041244
.await

database/src/pool/sqlite.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,32 @@ impl Connection for SqliteConnection {
911911
Vec::new()
912912
}
913913

914-
async fn get_bootstrap(
914+
async fn get_bootstrap(&self, aids: &[ArtifactIdNumber]) -> Vec<Option<Duration>> {
915+
aids.into_iter()
916+
.map(|aid| {
917+
self.raw_ref()
918+
.prepare(
919+
"
920+
select min(total)
921+
from (
922+
select sum(duration) as total
923+
from rustc_compilation
924+
where aid = ?
925+
group by cid
926+
)
927+
",
928+
)
929+
.unwrap()
930+
.query_row(params![&aid.0], |row| {
931+
Ok(Duration::from_nanos(row.get::<_, i64>(0)? as u64))
932+
})
933+
.optional()
934+
.unwrap()
935+
})
936+
.collect()
937+
}
938+
939+
async fn get_bootstrap_by_crate(
915940
&self,
916941
aids: &[ArtifactIdNumber],
917942
) -> HashMap<String, Vec<Option<Duration>>> {
@@ -928,15 +953,11 @@ impl Connection for SqliteConnection {
928953
.unwrap()
929954
.map(|r| r.unwrap())
930955
.collect();
931-
for (krate, duration) in rows {
956+
for (krate, min_duration) in rows {
932957
let v = results
933958
.entry(krate)
934-
.or_insert_with(|| Vec::with_capacity(aids.len()));
935-
936-
if v.len() != idx {
937-
v.resize_with(idx, || None);
938-
}
939-
v.push(Some(Duration::from_nanos(duration as u64)));
959+
.or_insert_with(|| vec![None; aids.len()]);
960+
v[idx] = Some(Duration::from_nanos(min_duration as u64));
940961
}
941962
}
942963

site/src/api.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ pub mod bootstrap {
133133
// (UTC timestamp, sha)
134134
pub commits: Vec<(i64, String)>,
135135
// Optional nanoseconds
136-
pub by_crate: HashMap<String, Vec<Option<u64>>>,
136+
pub by_crate_build_times: HashMap<String, Vec<Option<u64>>>,
137+
// Each commit's total rustc build time in nanoseconds
138+
pub total_build_times: Vec<Option<u64>>,
137139
}
138140
}
139141

site/src/comparison.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl ArtifactData {
314314
let data = data_from_series(series);
315315

316316
let bootstrap = conn
317-
.get_bootstrap(&[conn.artifact_id(&artifact).await])
317+
.get_bootstrap_by_crate(&[conn.artifact_id(&artifact).await])
318318
.await;
319319
let bootstrap = bootstrap
320320
.into_iter()

site/src/request_handlers/bootstrap.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ use crate::api::{bootstrap, ServerResult};
44
use crate::db::ArtifactId;
55
use crate::load::SiteCtxt;
66

7+
use std::time::Duration;
8+
79
pub async fn handle_bootstrap(
810
body: bootstrap::Request,
911
ctxt: &SiteCtxt,
1012
) -> ServerResult<bootstrap::Response> {
1113
log::info!("handle_bootstrap({:?})", body);
1214
let range = ctxt.data_range(body.start.clone()..=body.end.clone());
13-
let mut commits: Vec<ArtifactId> = range.iter().map(|c| c.clone().into()).collect();
15+
let commits: Vec<ArtifactId> = range.iter().map(|c| c.clone().into()).collect();
1416

1517
let conn = ctxt.conn().await;
1618
let ids = commits
@@ -19,8 +21,14 @@ pub async fn handle_bootstrap(
1921
.collect::<FuturesOrdered<_>>()
2022
.collect::<Vec<_>>()
2123
.await;
22-
let by_crate = conn.get_bootstrap(&ids).await;
23-
let mut by_crate = by_crate
24+
25+
let by_crate_build_times = conn.get_bootstrap_by_crate(&ids).await;
26+
27+
fn duration_as_nanos_u64(d: Duration) -> u64 {
28+
d.as_nanos() as u64
29+
}
30+
31+
let by_crate_build_times = by_crate_build_times
2432
.into_iter()
2533
.filter_map(|(k, v)| {
2634
// We show any line that has at least one point exceeding the
@@ -29,7 +37,7 @@ pub async fn handle_bootstrap(
2937
Some((
3038
k,
3139
v.into_iter()
32-
.map(|v| v.map(|d| d.as_nanos() as u64))
40+
.map(|v| v.map(duration_as_nanos_u64))
3341
.collect(),
3442
))
3543
} else {
@@ -38,17 +46,12 @@ pub async fn handle_bootstrap(
3846
})
3947
.collect::<hashbrown::HashMap<String, Vec<Option<u64>>>>();
4048

41-
// Don't return commits/nulls for completely null commits at the beginning
42-
let start: usize = by_crate
43-
.values()
44-
.filter_map(|series| series.iter().position(|v| v.is_some()))
45-
.min()
46-
.unwrap_or(0);
47-
48-
commits = commits.split_off(start);
49-
for series in by_crate.values_mut() {
50-
*series = series.split_off(start);
51-
}
49+
let total_build_times = conn
50+
.get_bootstrap(&ids)
51+
.await
52+
.into_iter()
53+
.map(|v| v.map(duration_as_nanos_u64))
54+
.collect();
5255

5356
Ok(bootstrap::Response {
5457
commits: commits
@@ -58,6 +61,7 @@ pub async fn handle_bootstrap(
5861
ArtifactId::Tag(_) => todo!(),
5962
})
6063
.collect(),
61-
by_crate,
64+
by_crate_build_times,
65+
total_build_times,
6266
})
6367
}

site/static/bootstrap.html

+27-12
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@
7272
<h2>Loading &amp; rendering data..</h2>
7373
<h3>This may take a while!</h3>
7474
</div>
75-
<div id="charts"></div>
75+
<div id="byCrateChart"></div>
76+
<div id="totalChart"></div>
7677
<div id="as-of"></div>
7778
<a href="https://github.com/rust-lang-nursery/rustc-perf">
7879
<img style="position: absolute; top: 0; right: 0; border: 0;"
@@ -232,36 +233,50 @@ <h3>This may take a while!</h3>
232233
}
233234

234235
function renderPlots(data, state) {
235-
let seriesOpts = [{}];
236+
let byChartSeriesOpts = [{}];
236237

237238
let xVals = data.commits.map(c => c[0]);
238-
let plotData = [xVals];
239+
let byChartPlotData = [xVals];
239240
// https://sashamaps.net/docs/resources/20-colors/
240241
let colors = [
241242
'#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231',
242243
'#911eb4', '#46f0f0', '#f032e6', '#a09b13', '#0ab0be',
243244
'red', 'green', 'blue', 'purple'
244245
];
245-
let crates = Object.keys(data.by_crate).sort();
246+
let crates = Object.keys(data.by_crate_build_times).sort();
246247
for (let crate of crates) {
247-
plotData.push(data.by_crate[crate]);
248+
byChartPlotData.push(data.by_crate_build_times[crate]);
248249

249-
seriesOpts.push({
250+
byChartSeriesOpts.push({
250251
label: crate,
251252
stroke: colors.length ? colors.pop() : 'black',
252253
});
253254
}
254255

255-
let plotOpts = genPlotOpts({
256-
title: "Bootstrap timings for crates >= 30 seconds",
256+
let byChartPlotOpts = genPlotOpts({
257+
title: "Bootstrap time for crates >= 30 seconds",
257258
width: Math.floor(window.innerWidth) - 16,
258-
height: window.innerHeight * 0.75,
259+
height: window.innerHeight * 0.56,
259260
yAxisLabel: "",
260-
series: seriesOpts,
261+
series: byChartSeriesOpts,
261262
commits: data.commits,
262263
});
263264

264-
let u = new uPlot(plotOpts, plotData, document.querySelector("#charts"));
265+
let byChartPlot = new uPlot(byChartPlotOpts, byChartPlotData, document.querySelector("#byCrateChart"));
266+
267+
let totalPlotData = [xVals, data.total_build_times];
268+
269+
let totalPlotOpts = genPlotOpts({
270+
title: "Total bootstrap time",
271+
width: Math.floor(window.innerWidth) - 16,
272+
height: window.innerHeight * 0.26,
273+
yAxisLabel: "",
274+
series: [{}, { label: "rustc", stroke: '#7cb5ec' }],
275+
commits: data.commits,
276+
});
277+
278+
let totalPlot = new uPlot(totalPlotOpts, totalPlotData, document.querySelector("#totalChart"));
279+
265280
document.querySelector("#loading").style.display = 'none';
266281
}
267282

@@ -291,4 +306,4 @@ <h3>This may take a while!</h3>
291306
</script>
292307
</body>
293308

294-
</html>
309+
</html>

0 commit comments

Comments
 (0)