|
30 | 30 | //!
|
31 | 31 | //! ## Jobserver
|
32 | 32 | //!
|
33 |
| -//! Cargo and rustc have a somewhat non-trivial jobserver relationship with each |
34 |
| -//! other, which is due to scaling issues with sharing a single jobserver |
35 |
| -//! amongst what is potentially hundreds of threads of work on many-cored |
36 |
| -//! systems on (at least) Linux, and likely other platforms as well. |
| 33 | +//! As of Feb. 2023, Cargo and rustc have a relatively simple jobserver |
| 34 | +//! relationship with each other. They share a single jobserver amongst what |
| 35 | +//! is potentially hundreds of threads of work on many-cored systems. |
| 36 | +//! The jobserver could come from either the environment (e.g., from a `make` |
| 37 | +//! invocation), or from Cargo creating its own jobserver server if there is no |
| 38 | +//! jobserver to inherit from. |
37 | 39 | //!
|
38 | 40 | //! Cargo wants to complete the build as quickly as possible, fully saturating
|
39 |
| -//! all cores (as constrained by the -j=N) parameter. Cargo also must not spawn |
| 41 | +//! all cores (as constrained by the `-j=N`) parameter. Cargo also must not spawn |
40 | 42 | //! more than N threads of work: the total amount of tokens we have floating
|
41 | 43 | //! around must always be limited to N.
|
42 | 44 | //!
|
43 |
| -//! It is not really possible to optimally choose which crate should build first |
44 |
| -//! or last; nor is it possible to decide whether to give an additional token to |
45 |
| -//! rustc first or rather spawn a new crate of work. For now, the algorithm we |
46 |
| -//! implement prioritizes spawning as many crates (i.e., rustc processes) as |
47 |
| -//! possible, and then filling each rustc with tokens on demand. |
| 45 | +//! It is not really possible to optimally choose which crate should build |
| 46 | +//! first or last; nor is it possible to decide whether to give an additional |
| 47 | +//! token to rustc first or rather spawn a new crate of work. The algorithm in |
| 48 | +//! Cargo prioritizes spawning as many crates (i.e., rustc processes) as |
| 49 | +//! possible. In short, the jobserver relationship among Cargo and rustc |
| 50 | +//! processes is **1 `cargo` to N `rustc`**. Cargo knows nothing beyond rustc |
| 51 | +//! processes in terms of parallelism[^parallel-rustc]. |
48 | 52 | //!
|
49 |
| -//! We integrate with the [jobserver], originating from GNU make, to make sure |
50 |
| -//! that build scripts which use make to build C code can cooperate with us on |
51 |
| -//! the number of used tokens and avoid overfilling the system we're on. |
52 |
| -//! |
53 |
| -//! The jobserver is unfortunately a very simple protocol, so we enhance it a |
54 |
| -//! little when we know that there is a rustc on the other end. Via the stderr |
55 |
| -//! pipe we have to rustc, we get messages such as `NeedsToken` and |
56 |
| -//! `ReleaseToken` from rustc. |
57 |
| -//! |
58 |
| -//! [`NeedsToken`] indicates that a rustc is interested in acquiring a token, |
59 |
| -//! but never that it would be impossible to make progress without one (i.e., |
60 |
| -//! it would be incorrect for rustc to not terminate due to an unfulfilled |
61 |
| -//! `NeedsToken` request); we do not usually fulfill all `NeedsToken` requests for a |
62 |
| -//! given rustc. |
63 |
| -//! |
64 |
| -//! [`ReleaseToken`] indicates that a rustc is done with one of its tokens and |
65 |
| -//! is ready for us to re-acquire ownership — we will either release that token |
66 |
| -//! back into the general pool or reuse it ourselves. Note that rustc will |
67 |
| -//! inform us that it is releasing a token even if it itself is also requesting |
68 |
| -//! tokens; is up to us whether to return the token to that same rustc. |
69 |
| -//! |
70 |
| -//! `jobserver` also manages the allocation of tokens to rustc beyond |
71 |
| -//! the implicit token each rustc owns (i.e., the ones used for parallel LLVM |
72 |
| -//! work and parallel rustc threads). |
| 53 | +//! We integrate with the [jobserver] crate, originating from GNU make |
| 54 | +//! [POSIX jobserver], to make sure that build scripts which use make to |
| 55 | +//! build C code can cooperate with us on the number of used tokens and |
| 56 | +//! avoid overfilling the system we're on. |
73 | 57 | //!
|
74 | 58 | //! ## Scheduling
|
75 | 59 | //!
|
|
113 | 97 | //!
|
114 | 98 | //! See [`Message`] for all available message kinds.
|
115 | 99 | //!
|
| 100 | +//! [^parallel-rustc]: In fact, `jobserver` that Cargo uses also manages the |
| 101 | +//! allocation of tokens to rustc beyond the implicit token each rustc owns |
| 102 | +//! (i.e., the ones used for parallel LLVM work and parallel rustc threads). |
| 103 | +//! See also ["Rust Compiler Development Guide: Parallel Compilation"] |
| 104 | +//! and [this comment][rustc-codegen] in rust-lang/rust. |
| 105 | +//! |
| 106 | +//! ["Rust Compiler Development Guide: Parallel Compilation"]: https://rustc-dev-guide.rust-lang.org/parallel-rustc.html |
| 107 | +//! [rustc-codegen]: https://github.com/rust-lang/rust/blob/5423745db8b434fcde54888b35f518f00cce00e4/compiler/rustc_codegen_ssa/src/back/write.rs#L1204-L1217 |
116 | 108 | //! [jobserver]: https://docs.rs/jobserver
|
117 |
| -//! [`NeedsToken`]: Message::NeedsToken |
118 |
| -//! [`ReleaseToken`]: Message::ReleaseToken |
| 109 | +//! [POSIX jobserver]: https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html |
119 | 110 | //! [`push`]: Queue::push
|
120 | 111 | //! [`push_bounded`]: Queue::push_bounded
|
121 | 112 |
|
|
0 commit comments