Skip to content

Commit 1e52a8c

Browse files
authored
Add initial integration for --json=timings behing -Zsection-timings (#15780)
### What does this PR try to resolve? This PR adds initial support into Cargo for JSON timing sections, implemented in rustc in rust-lang/rust#142123. This allows Cargo to read frontend/codegen/linking time from rustc, and thus reporting slightly more detailed data in the `cargo build --timings` output. The PR modifies Cargo to tell rustc to emit the section messages (`--json=...,timings`), and it adds the section timings data to the HTML table output and the JSON output. It does not yet integration different sections in the HTML unit chart (I want to do that as a follow-up). Note that the JSON timings are currently only supported on the nightly compiler (they are not stabilized). The new behavior is thus gated behing an unstable Cargo flag (`-Zsection-timings`). When the flag is unused, the HTML table should look more or less the same as before, just that the code now supports both options. ### How to test and review this PR? You can run e.g. this to generate the timing report with a nightly compiler: ```bash export RUSTC=`rustup +nightly which rustc` target/debug/cargo build -Zsection-timings --timings ``` on some crate, e.g. [ripgrep](https://github.com/BurntSushi/ripgrep). Tracking issue: #15817
2 parents 6bf996c + 199e9e7 commit 1e52a8c

File tree

8 files changed

+323
-32
lines changed

8 files changed

+323
-32
lines changed

src/cargo/core/compiler/job_queue/job_state.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use cargo_util::ProcessBuilder;
77
use crate::CargoResult;
88
use crate::core::compiler::build_runner::OutputFile;
99
use crate::core::compiler::future_incompat::FutureBreakageItem;
10+
use crate::core::compiler::timings::SectionTiming;
1011
use crate::util::Queue;
1112

1213
use super::{Artifact, DiagDedupe, Job, JobId, Message};
@@ -143,6 +144,10 @@ impl<'a, 'gctx> JobState<'a, 'gctx> {
143144
.push(Message::Finish(self.id, Artifact::Metadata, Ok(())));
144145
}
145146

147+
pub fn on_section_timing_emitted(&self, section: SectionTiming) {
148+
self.messages.push(Message::SectionTiming(self.id, section));
149+
}
150+
146151
/// Drives a [`Job`] to finish. This ensures that a [`Message::Finish`] is
147152
/// sent even if our job panics.
148153
pub(super) fn run_to_finish(self, job: Job) {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ pub use self::job::{Job, Work};
133133
pub use self::job_state::JobState;
134134
use super::build_runner::OutputFile;
135135
use super::custom_build::Severity;
136-
use super::timings::Timings;
136+
use super::timings::{SectionTiming, Timings};
137137
use super::{BuildContext, BuildPlan, BuildRunner, CompileMode, Unit};
138138
use crate::core::compiler::descriptive_pkg_name;
139139
use crate::core::compiler::future_incompat::{
@@ -374,6 +374,7 @@ enum Message {
374374
Token(io::Result<Acquired>),
375375
Finish(JobId, Artifact, CargoResult<()>),
376376
FutureIncompatReport(JobId, Vec<FutureBreakageItem>),
377+
SectionTiming(JobId, SectionTiming),
377378
}
378379

379380
impl<'gctx> JobQueue<'gctx> {
@@ -714,6 +715,9 @@ impl<'gctx> DrainState<'gctx> {
714715
let token = acquired_token.context("failed to acquire jobserver token")?;
715716
self.tokens.push(token);
716717
}
718+
Message::SectionTiming(id, section) => {
719+
self.timings.unit_section_timing(id, &section);
720+
}
717721
}
718722

719723
Ok(())

src/cargo/core/compiler/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ use self::output_depinfo::output_depinfo;
9090
use self::output_sbom::build_sbom;
9191
use self::unit_graph::UnitDep;
9292
use crate::core::compiler::future_incompat::FutureIncompatReport;
93+
use crate::core::compiler::timings::SectionTiming;
9394
pub use crate::core::compiler::unit::{Unit, UnitInterner};
9495
use crate::core::manifest::TargetSourcePath;
9596
use crate::core::profiles::{PanicStrategy, Profile, StripInner};
@@ -104,6 +105,7 @@ use cargo_util_schemas::manifest::TomlDebugInfo;
104105
use cargo_util_schemas::manifest::TomlTrimPaths;
105106
use cargo_util_schemas::manifest::TomlTrimPathsValue;
106107
use rustfix::diagnostics::Applicability;
108+
pub(crate) use timings::CompilationSection;
107109

108110
const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version";
109111

@@ -1095,6 +1097,12 @@ fn add_allow_features(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuild
10951097
///
10961098
/// [`--error-format`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#--error-format-control-how-errors-are-produced
10971099
fn add_error_format_and_color(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuilder) {
1100+
let enable_timings = build_runner.bcx.gctx.cli_unstable().section_timings
1101+
&& !build_runner.bcx.build_config.timing_outputs.is_empty();
1102+
if enable_timings {
1103+
cmd.arg("-Zunstable-options");
1104+
}
1105+
10981106
cmd.arg("--error-format=json");
10991107
let mut json = String::from("--json=diagnostic-rendered-ansi,artifacts,future-incompat");
11001108

@@ -1104,6 +1112,11 @@ fn add_error_format_and_color(build_runner: &BuildRunner<'_, '_>, cmd: &mut Proc
11041112
}
11051113
_ => {}
11061114
}
1115+
1116+
if enable_timings {
1117+
json.push_str(",timings");
1118+
}
1119+
11071120
cmd.arg(json);
11081121

11091122
let gctx = build_runner.bcx.gctx;
@@ -1957,6 +1970,12 @@ fn on_stderr_line_inner(
19571970
return Ok(true);
19581971
}
19591972

1973+
let res = serde_json::from_str::<SectionTiming>(compiler_message.get());
1974+
if let Ok(timing_record) = res {
1975+
state.on_section_timing_emitted(timing_record);
1976+
return Ok(false);
1977+
}
1978+
19601979
// Depending on what we're emitting from Cargo itself, we figure out what to
19611980
// do with this JSON message.
19621981
match options.format {

0 commit comments

Comments
 (0)