forked from mozilla/sccache
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit alters the main sccache server to operate and orchestrate its own GNU make style jobserver. This is primarily intended for interoperation with rustc itself. The Rust compiler currently has a multithreaded mode where it will execute code generation and optimization on the LLVM side of things in parallel. This parallelism, however, can overload a machine quickly if not properly accounted for (e.g. if 10 rustcs all spawn 10 threads...). The usage of a GNU make style jobserver is intended to arbitrate and rate limit all these rustc instances to ensure that one build's maximal parallelism never exceeds a particular amount. Currently for Rust Cargo is the primary driver for setting up a jobserver. Cargo will create this and manage this per compilation, ensuring that any one `cargo build` invocation never exceeds a maximal parallelism. When sccache enters the picture, however, the story gets slightly more odd. The jobserver implementation on Unix relies on inheritance of file descriptors in spawned processes. With sccache, however, there's no inheritance as the actual rustc invocation is spawned by the server, not the client. In this case the env vars used to configure the jobsever are usually incorrect. To handle this problem this commit bakes a jobserver directly into sccache itself. The jobserver then overrides whatever jobserver the client has configured in its own env vars to ensure correct operation. The settings of each jobserver may be misconfigured (there's no way to configure sccache's jobserver right now), but hopefully that's not too much of a problem for the forseeable future. The implementation here was to provide a thin wrapper around the `jobserver` crate with a futures-based interface. This interface was then hooked into the mock command infrastructure to automatically acquire a jobserver token when spawning a process and automatically drop the token when the process exits. Additionally, all spawned processes will now automatically receive a configured jobserver. cc rust-lang/rust#42867, the original motivation for this commit
- Loading branch information
1 parent
aa5f93f
commit a38da80
Showing
13 changed files
with
238 additions
and
111 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
extern crate jobserver; | ||
|
||
use std::io; | ||
use std::process::Command; | ||
use std::sync::Arc; | ||
|
||
use futures::prelude::*; | ||
use futures::sync::mpsc; | ||
use futures::sync::oneshot; | ||
use num_cpus; | ||
|
||
use errors::*; | ||
|
||
pub use self::jobserver::Acquired; | ||
|
||
#[derive(Clone)] | ||
pub struct Client { | ||
helper: Arc<jobserver::HelperThread>, | ||
inner: jobserver::Client, | ||
tx: mpsc::UnboundedSender<oneshot::Sender<io::Result<Acquired>>> | ||
} | ||
|
||
impl Client { | ||
// unsafe because `from_env` is unsafe (can use the wrong fds) | ||
pub unsafe fn new() -> Client { | ||
match jobserver::Client::from_env() { | ||
Some(c) => Client::_new(c), | ||
None => Client::new_num(num_cpus::get()), | ||
} | ||
} | ||
|
||
pub fn new_num(num: usize) -> Client { | ||
let inner = jobserver::Client::new(num) | ||
.expect("failed to create jobserver"); | ||
Client::_new(inner) | ||
} | ||
|
||
fn _new(inner: jobserver::Client) -> Client { | ||
let (tx, rx) = mpsc::unbounded::<oneshot::Sender<_>>(); | ||
let mut rx = rx.wait(); | ||
let helper = inner.clone().into_helper_thread(move |token| { | ||
if let Some(Ok(sender)) = rx.next() { | ||
drop(sender.send(token)); | ||
} | ||
}).expect("failed to spawn helper thread"); | ||
|
||
Client { | ||
inner: inner, | ||
helper: Arc::new(helper), | ||
tx: tx, | ||
} | ||
} | ||
|
||
/// Configures this jobserver to be inherited by the specified command | ||
pub fn configure(&self, cmd: &mut Command) { | ||
self.inner.configure(cmd) | ||
} | ||
|
||
/// Returns a future that represents an acquired jobserver token. | ||
/// | ||
/// This should be invoked before any "work" is spawend (for whatever the | ||
/// defnition of "work" is) to ensure that the system is properly | ||
/// rate-limiting itself. | ||
pub fn acquire(&self) -> SFuture<Acquired> { | ||
let (tx, rx) = oneshot::channel(); | ||
self.helper.request_token(); | ||
self.tx.unbounded_send(tx).unwrap(); | ||
Box::new(rx.chain_err(|| "jobserver helper panicked") | ||
.and_then(|t| t.chain_err(|| "failed to acquire jobserver token"))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.