-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clean up rustdoc startup #102769
Clean up rustdoc startup #102769
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! Two of the comments I left I found you'd addressed in a later commit :)
In other words, rustdoc calls into
rustc_interface
at three different
levels. It's a bit confused, and feels like code where functionality has
been added by different people at different times without fully
understanding how the globally accessible stuff is set up.
Yuuuuuup
@jyn514: I have updated with a new commit that uses |
You're very welcome! @bors r+ |
Clean up rustdoc startup Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help. Best reviewed one commit at a time. r? `@jyn514`
Clean up rustdoc startup Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help. Best reviewed one commit at a time. r? ``@jyn514``
Clean up rustdoc startup Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help. Best reviewed one commit at a time. r? ```@jyn514```
Rollup of 7 pull requests Successful merges: - rust-lang#102623 (translation: eager translation) - rust-lang#102769 (Clean up rustdoc startup) - rust-lang#102830 (Unify `tcx.constness` query and param env constness checks) - rust-lang#102847 (impl AsFd and AsRawFd for io::{Stdin, Stdout, Stderr}, not the sys versions) - rust-lang#102883 (Fix stabilization of `feature(half_open_range_patterns)`) - rust-lang#102936 (rustdoc: remove unused CSS `nav.sum`) - rust-lang#102940 (Update books) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Clean up rustdoc startup Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help. Best reviewed one commit at a time. r? ````@jyn514````
failed in rollup but going to try it again individually @bors rollup=iffy |
⌛ Testing commit 1f0463a with merge 7d6f6a66e3d69e4045adcf7dcd58681175b04450... |
💔 Test failed - checks-actions |
This comment has been minimized.
This comment has been minimized.
c53d338
to
f87fd1f
Compare
r? @jyn514 |
☔ The latest upstream changes (presumably #102992) made this pull request unmergeable. Please resolve the merge conflicts. |
rustc's startup has several layers, including: - `interface::run_compiler` passes a closure, `f`, to `run_in_thread_pool_with_globals`, which creates a thread pool, sets up session globals, and passes `f` to `create_compiler_and_run`. - `create_compiler_and_run` creates a `Session`, a `Compiler`, sets the source map, and calls `f`. rustdoc is a bit different. - `main_args` calls `main_options` via `run_in_thread_pool_with_globals`, which (again) creates a thread pool (hardcoded to a single thread!) and sets up session globals. - `main_options` has four different paths. - The second one calls `interface::run_compiler`, which redoes the `run_in_thread_pool_with_globals`! This is bad. - The fourth one calls `interface::create_compiler_and_run`, which is reasonable. - The first and third ones don't do anything of note involving the above functions, except for some symbol interning which requires session globals. In other words, rustdoc calls into `rustc_interface` at three different levels. It's a bit confused, and feels like code where functionality has been added by different people at different times without fully understanding how the globally accessible stuff is set up. This commit tidies things up. It removes the `run_in_thread_pool_with_globals` call in `main_args`, and adjust the four paths in `main_options` as follows. - `markdown::test` calls `test::test_main`, which provides its own parallelism and so doesn't need a thread pool. It had one small use of symbol interning, which required session globals, but the commit removes this. - `doctest::run` already calls `interface::run_compiler`, so it doesn't need further adjustment. - `markdown::render` is simple but needs session globals for interning (which can't easily be removed), so it's now wrapped in `create_session_globals_then`. - The fourth path now uses `interface::run_compiler`, which is equivalent to the old `run_in_thread_pool_with_globals` + `create_compiler_and_run` pairing.
There is no longer any need for them to be separate.
It has a single call site, and removing it slightly improves the confusing tangle of nested closures present at startup.
It has a single call site.
This avoids the need for a degenerate `Lrc::get_mut` call.
It turns out `markdown::render` is more complex than it first appears, because it can invoke `doctest::make_test`, which requires session globals and a thread pool. So this commit changes it to use `interface::run_compiler`. Three of the four paths in `main_args` now use `interface::run_compiler`.
By moving `RenderOptions` out of `Option`, because the two structs' uses are almost entirely separate. The only complication is that `unstable_features` is needed in both structs, but it's a tiny `Copy` type so its duplication seems fine.
f87fd1f
to
ca2561a
Compare
@bors r+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (2efc90e): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. Footnotes |
Clarify startup A small follow-up to rust-lang#102769. r? `@jyn514`
/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need | ||
/// for `'static` bounds. | ||
#[cfg(not(parallel_compiler))] | ||
fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R { | ||
// SAFETY: join() is called immediately, so any closure captures are still | ||
// alive. | ||
match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() { | ||
Ok(v) => v, | ||
Err(e) => panic::resume_unwind(e), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please never inline safe functions that contain unsafe
code!
(Also, not as important here, but "single call site" is a really bad metric, unless you can find where other callsites were removed in the past or anything of the worst - often single-call-site functions are separate for semantic reasons!)
The purpose of such a function is to encapsulate the unsafety. Inlining could cause unsound interactions with surrounding code in the caller! And increases complexity in analyzing the correctness of the code, regardless of what you may think about some subject readability metric.
In the end this was fine because of the move to the new scoped threads, but this is pretty dangerous to do in the first place, and IMO should've been a PR on its own anyway (that has "scoped threads" or similar in the PR title, assuming going the full route to the new scoped thread API).
// JUSTIFICATION: before session exists, only config | ||
#[allow(rustc::bad_opt_access)] | ||
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { | ||
trace!("run_compiler"); | ||
util::run_in_thread_pool_with_globals( | ||
config.opts.edition, | ||
config.opts.unstable_opts.threads, | ||
|| create_compiler_and_run(config, f), | ||
|| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the other comment:
"single call site" is a really bad metric, unless you can find where other callsites were removed in the past or anything of the worst - often single-call-site functions are separate for semantic reasons!
Here it looks like #[allow(rustc::bad_opt_access)]
only applied to config.opts.edition,
and config.opts.unstable_opts.threads,
but now applies to the entire closure.
Not to mention the indentation makes the readability improvement here a bit dubious.
Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help.
Best reviewed one commit at a time.
r? @jyn514