rust/compiler/rustc_errors/src
Urgau 2011ab5152
Rollup merge of #142123 - Kobzol:timings, r=nnethercote
Implement initial support for timing sections (`--json=timings`)

This PR implements initial support for emitting high-level compilation section timings. The idea is to provide a very lightweight way of emitting durations of various compilation sections (frontend, backend, linker, or on a more granular level macro expansion, typeck, borrowck, etc.). The ultimate goal is to stabilize this output (in some form), make Cargo pass `--json=timings` and then display this information in the HTML output of `cargo build --timings`, to make it easier to quickly profile "what takes so long" during the compilation of a Cargo project. I would personally also like if Cargo printed some of this information in the interactive `cargo build` output, but the `build --timings` use-case is the main one.

Now, this information is already available with several other sources, but I don't think that we can just use them as they are, which is why I proposed a new way of outputting this data (`--json=timings`):
- This data is available under `-Zself-profile`, but that is very expensive and forever unstable. It's just a too big of a hammer to tell us the duration it took to run the linker.
- It could also be extracted with `-Ztime-passes`. That is pretty much "for free" in terms of performance, and it can be emitted in a structured form to JSON via `-Ztime-passes-format=json`. I guess that one alternative might be to stabilize this flag in some form, but that form might just be `--json=timings`? I guess what we could do in theory is take the already emitted time passes and reuse them for `--json=timings`. Happy to hear suggestions!

I'm sending this PR mostly for a vibeck, to see if the way I implemented it is passable. There are some things to figure out:
- How do we represent the sections? Originally I wanted to output `{ section, duration }`, but then I realized that it might be more useful to actually emit `start` and `end` events. Both because it enables to see the output incrementally (in case compilation takes a long time and you read the outputs directly, or Cargo decides to show this data in `cargo build` some day in the future), and because it makes it simpler to represent hierarchy (see below). The timestamps currently emit microseconds elapsed from a predetermined point in time (~start of rustc), but otherwise they are fully opaque, and should be only ever used to calculate the duration using `end - start`. We could also precompute the duration for the user in the `end` event, but that would require doing more work in rustc, which I would ideally like to avoid :P
- Do we want to have some form of hierarchy? I think that it would be nice to show some more granular sections rather than just frontend/backend/linker (e.g. macro expansion, typeck and borrowck as a part of the frontend). But for that we would need some way of representing hierarchy. A simple way would be something like `{ parent: "frontend" }`, but I realized that with start/end timestamps we get the hierarchy "for free", only the client will need to reconstruct it from the order of start/end events (e.g. `start A`, `start B` means that `B` is a child of `A`).
- What exactly do we want to stabilize? This is probably a question for later. I think that we should definitely stabilize the format of the emitted JSON objects, and *maybe* some specific section names (but we should also make it clear that they can be missing, e.g. you don't link everytime you invoke `rustc`).

The PR be tested e.g. with `rustc +stage1 src/main.rs --json=timings --error-format=json -Zunstable-options` on a crate without dependencies (it is not easy to use `--json` with stock Cargo, because it also passes this flag to `rustc`, so this will later need Cargo integration to be usable with it).

Zulip discussions: [#t-compiler > Outputting time spent in various compiler sections](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Outputting.20time.20spent.20in.20various.20compiler.20sections/with/518850162)

MCP: https://github.com/rust-lang/compiler-team/issues/873

r? ``@nnethercote``
2025-06-18 19:40:32 +02:00
..
json Rustfmt 2025-02-08 22:12:13 +00:00
markdown Use default field values in markdown::parse::Context 2025-03-03 20:04:20 +00:00
annotate_snippet_emitter_writer.rs Split ExpectationLintId off Level 2025-04-03 09:17:55 +00:00
codes.rs Stop using String for error codes. 2024-01-29 07:41:41 +11:00
diagnostic.rs Remove an unnecessary use of Box::into_inner. 2025-05-27 02:06:40 +10:00
diagnostic_impls.rs Move eager translation to a method on Diag 2025-04-16 21:38:59 -04:00
emitter.rs Add infrastructure for emitting timing sections 2025-06-16 11:51:17 +02:00
error.rs Reformat use declarations. 2024-07-29 08:26:52 +10:00
json.rs Add infrastructure for emitting timing sections 2025-06-16 11:51:17 +02:00
lib.rs Rollup merge of #142123 - Kobzol:timings, r=nnethercote 2025-06-18 19:40:32 +02:00
lock.rs Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
registry.rs Reformat use declarations. 2024-07-29 08:26:52 +10:00
snippet.rs Use abs_diff where applicable 2025-03-27 18:29:06 +00:00
styled_buffer.rs Fix rustdoc test 2025-03-07 17:55:08 +00:00
tests.rs Delete the cfg(not(parallel)) serial compiler 2024-11-12 13:38:58 +00:00
timings.rs Add infrastructure for emitting timing sections 2025-06-16 11:51:17 +02:00
translation.rs Convert Option<&Lrc<T>> return types to Option<&T>. 2024-10-07 13:56:29 +11:00