Skip to content

Commit 8ee3d92

Browse files
committed
Auto merge of #7731 - Mark-Simulacrum:chatty-jobserver, r=alexcrichton
Scalable jobserver for rustc This refactors the job queue code for support of [per-rustc process jobservers](rust-lang/rust#67398). Furthermore, it also cleans up the code and refactors the main loop to be more amenable to understanding (splitting into methods and such). Assignment of tokens to either rustc "threads" or processes is dedicated to the main loop, which proceeds in a strict "least recently requested" fashion among both thread and process token requests. Specifically, we will first allocate tokens to all pending process token requests (i.e., high-level units of work), and then (in per-rustc jobserver mode) follow up by assigning any remaining tokens to rustcs, again in the order that requests came into cargo (first request served first). It's not quite clear that that model is good (no modeling or so has been done). On the other hand this strategy should mean that long-running crates will get more thread tokens once we bottom out in terms of rustc parallelism than short-running crates, which means that crates like syn which start early on but finish pretty late should hopefully get more parallelism nicely (without any more complex heuristics). One plausible change that may be worth exploring is making the assignment prefer earlier rustc's, globally, rather than first attempting to spawn new crates and only then increasing parallelism for old crates. syn for example frequently gets compiled in the early storm of dozens of crates so is somewhat unlikely to have parallelism, until fairly late in its compilation. We also currently conflate under this model the rayon threads and codegen threads. Eventually inside rustc those will probably(?) also be just one thing, and the rustc side of this implementation provides no information as to what the token request is for so we can't do better here yet.
2 parents 9d11cd1 + 7e3e1b1 commit 8ee3d92

File tree

5 files changed

+507
-170
lines changed

5 files changed

+507
-170
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ pub struct Context<'a, 'cfg> {
6969
/// metadata files in addition to the rlib itself. This is only filled in
7070
/// when `pipelining` above is enabled.
7171
rmeta_required: HashSet<Unit<'a>>,
72+
73+
/// When we're in jobserver-per-rustc process mode, this keeps those
74+
/// jobserver clients for each Unit (which eventually becomes a rustc
75+
/// process).
76+
pub rustc_clients: HashMap<Unit<'a>, Client>,
7277
}
7378

7479
impl<'a, 'cfg> Context<'a, 'cfg> {
@@ -112,6 +117,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
112117
unit_dependencies,
113118
files: None,
114119
rmeta_required: HashSet::new(),
120+
rustc_clients: HashMap::new(),
115121
pipelining,
116122
})
117123
}
@@ -491,4 +497,23 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
491497
pub fn rmeta_required(&self, unit: &Unit<'a>) -> bool {
492498
self.rmeta_required.contains(unit) || self.bcx.config.cli_unstable().timings.is_some()
493499
}
500+
501+
pub fn new_jobserver(&mut self) -> CargoResult<Client> {
502+
let tokens = self.bcx.build_config.jobs as usize;
503+
let client = Client::new(tokens).chain_err(|| "failed to create jobserver")?;
504+
505+
// Drain the client fully
506+
for i in 0..tokens {
507+
while let Err(e) = client.acquire_raw() {
508+
anyhow::bail!(
509+
"failed to fully drain {}/{} token from jobserver at startup: {:?}",
510+
i,
511+
tokens,
512+
e,
513+
);
514+
}
515+
}
516+
517+
Ok(client)
518+
}
494519
}

0 commit comments

Comments
 (0)