Skip to content

Commit b176285

Browse files
committed
Auto merge of rust-lang#49094 - alexcrichton:print-step-duration, r=kennytm
ci: Print out how long each step takes on CI This commit updates CI configuration to inform rustbuild that it should print out how long each step takes on CI. This'll hopefully allow us to track the duration of steps over time and follow regressions a bit more closesly (as well as have closer analysis of differences between two builds). cc rust-lang#48829
2 parents e575773 + 1b5eb17 commit b176285

File tree

5 files changed

+81
-22
lines changed

5 files changed

+81
-22
lines changed

config.toml.example

+4
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@
186186
# essentially skipping stage0 as the local compiler is recompiling itself again.
187187
#local-rebuild = false
188188

189+
# Print out how long each rustbuild step took (mostly intended for CI and
190+
# tracking over time)
191+
#print-step-timings = false
192+
189193
# =============================================================================
190194
# General install configuration options
191195
# =============================================================================

src/bootstrap/bin/rustc.rs

+45-20
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ extern crate bootstrap;
3131

3232
use std::env;
3333
use std::ffi::OsString;
34-
use std::str::FromStr;
34+
use std::io;
3535
use std::path::PathBuf;
36-
use std::process::{Command, ExitStatus};
36+
use std::process::Command;
37+
use std::str::FromStr;
38+
use std::time::Instant;
3739

3840
fn main() {
3941
let mut args = env::args_os().skip(1).collect::<Vec<_>>();
@@ -90,7 +92,7 @@ fn main() {
9092
};
9193
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
9294
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
93-
let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
95+
let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
9496

9597
let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
9698
let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -103,6 +105,7 @@ fn main() {
103105
.arg(format!("stage{}", stage))
104106
.env(bootstrap::util::dylib_path_var(),
105107
env::join_paths(&dylib_path).unwrap());
108+
let mut maybe_crate = None;
106109

107110
if let Some(target) = target {
108111
// The stage0 compiler has a special sysroot distinct from what we
@@ -134,6 +137,7 @@ fn main() {
134137
.find(|a| &*a[0] == "--crate-name")
135138
.unwrap();
136139
let crate_name = &*crate_name[1];
140+
maybe_crate = Some(crate_name);
137141

138142
// If we're compiling specifically the `panic_abort` crate then we pass
139143
// the `-C panic=abort` option. Note that we do not do this for any
@@ -281,31 +285,52 @@ fn main() {
281285
eprintln!("libdir: {:?}", libdir);
282286
}
283287

284-
// Actually run the compiler!
285-
std::process::exit(if let Some(ref mut on_fail) = on_fail {
286-
match cmd.status() {
287-
Ok(s) if s.success() => 0,
288-
_ => {
289-
println!("\nDid not run successfully:\n{:?}\n-------------", cmd);
290-
exec_cmd(on_fail).expect("could not run the backup command");
291-
1
288+
if let Some(mut on_fail) = on_fail {
289+
let e = match cmd.status() {
290+
Ok(s) if s.success() => std::process::exit(0),
291+
e => e,
292+
};
293+
println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
294+
exec_cmd(&mut on_fail).expect("could not run the backup command");
295+
std::process::exit(1);
296+
}
297+
298+
if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
299+
if let Some(krate) = maybe_crate {
300+
let start = Instant::now();
301+
let status = cmd
302+
.status()
303+
.expect(&format!("\n\n failed to run {:?}", cmd));
304+
let dur = start.elapsed();
305+
306+
let is_test = args.iter().any(|a| a == "--test");
307+
eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}",
308+
krate.to_string_lossy(),
309+
is_test,
310+
dur.as_secs(),
311+
dur.subsec_nanos() / 1_000_000);
312+
313+
match status.code() {
314+
Some(i) => std::process::exit(i),
315+
None => {
316+
eprintln!("rustc exited with {}", status);
317+
std::process::exit(0xfe);
318+
}
292319
}
293320
}
294-
} else {
295-
std::process::exit(match exec_cmd(&mut cmd) {
296-
Ok(s) => s.code().unwrap_or(0xfe),
297-
Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
298-
})
299-
})
321+
}
322+
323+
let code = exec_cmd(&mut cmd).expect(&format!("\n\n failed to run {:?}", cmd));
324+
std::process::exit(code);
300325
}
301326

302327
#[cfg(unix)]
303-
fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
328+
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
304329
use std::os::unix::process::CommandExt;
305330
Err(cmd.exec())
306331
}
307332

308333
#[cfg(not(unix))]
309-
fn exec_cmd(cmd: &mut Command) -> ::std::io::Result<ExitStatus> {
310-
cmd.status()
334+
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
335+
cmd.status().map(|status| status.code().unwrap())
311336
}

src/bootstrap/builder.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use std::any::Any;
12-
use std::cell::RefCell;
12+
use std::cell::{Cell, RefCell};
1313
use std::collections::BTreeSet;
1414
use std::env;
1515
use std::fmt::Debug;
@@ -18,6 +18,7 @@ use std::hash::Hash;
1818
use std::ops::Deref;
1919
use std::path::{Path, PathBuf};
2020
use std::process::Command;
21+
use std::time::{Instant, Duration};
2122

2223
use compile;
2324
use install;
@@ -40,6 +41,7 @@ pub struct Builder<'a> {
4041
pub kind: Kind,
4142
cache: Cache,
4243
stack: RefCell<Vec<Box<Any>>>,
44+
time_spent_on_dependencies: Cell<Duration>,
4345
}
4446

4547
impl<'a> Deref for Builder<'a> {
@@ -343,6 +345,7 @@ impl<'a> Builder<'a> {
343345
kind,
344346
cache: Cache::new(),
345347
stack: RefCell::new(Vec::new()),
348+
time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
346349
};
347350

348351
let builder = &builder;
@@ -383,6 +386,7 @@ impl<'a> Builder<'a> {
383386
kind,
384387
cache: Cache::new(),
385388
stack: RefCell::new(Vec::new()),
389+
time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
386390
};
387391

388392
if kind == Kind::Dist {
@@ -662,6 +666,10 @@ impl<'a> Builder<'a> {
662666
cargo.env("RUSTC_ON_FAIL", on_fail);
663667
}
664668

669+
if self.config.print_step_timings {
670+
cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1");
671+
}
672+
665673
cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
666674

667675
// Throughout the build Cargo can execute a number of build scripts
@@ -818,7 +826,24 @@ impl<'a> Builder<'a> {
818826
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
819827
stack.push(Box::new(step.clone()));
820828
}
821-
let out = step.clone().run(self);
829+
830+
let (out, dur) = {
831+
let start = Instant::now();
832+
let zero = Duration::new(0, 0);
833+
let parent = self.time_spent_on_dependencies.replace(zero);
834+
let out = step.clone().run(self);
835+
let dur = start.elapsed();
836+
let deps = self.time_spent_on_dependencies.replace(parent + dur);
837+
(out, dur - deps)
838+
};
839+
840+
if self.build.config.print_step_timings && dur > Duration::from_millis(100) {
841+
println!("[TIMING] {:?} -- {}.{:03}",
842+
step,
843+
dur.as_secs(),
844+
dur.subsec_nanos() / 1_000_000);
845+
}
846+
822847
{
823848
let mut stack = self.stack.borrow_mut();
824849
let cur_step = stack.pop().expect("step stack empty");

src/bootstrap/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ pub struct Config {
121121
pub quiet_tests: bool,
122122
pub test_miri: bool,
123123
pub save_toolstates: Option<PathBuf>,
124+
pub print_step_timings: bool,
124125

125126
// Fallback musl-root for all targets
126127
pub musl_root: Option<PathBuf>,
@@ -204,6 +205,7 @@ struct Build {
204205
openssl_static: Option<bool>,
205206
configure_args: Option<Vec<String>>,
206207
local_rebuild: Option<bool>,
208+
print_step_timings: Option<bool>,
207209
}
208210

209211
/// TOML representation of various global install decisions.
@@ -413,6 +415,7 @@ impl Config {
413415
set(&mut config.openssl_static, build.openssl_static);
414416
set(&mut config.configure_args, build.configure_args);
415417
set(&mut config.local_rebuild, build.local_rebuild);
418+
set(&mut config.print_step_timings, build.print_step_timings);
416419
config.verbose = cmp::max(config.verbose, flags.verbose);
417420

418421
if let Some(ref install) = toml.install {

src/ci/run.sh

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ source "$ci_dir/shared.sh"
2525

2626
if [ "$TRAVIS" == "true" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
2727
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests"
28+
else
29+
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings"
2830
fi
2931

3032
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"

0 commit comments

Comments
 (0)