-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add support for make jobservers #1744
Comments
Note that this could also be used for the compiler's own internal parallel codegen and possible future parallel compilation, so this could be quite useful! |
Our contributors with less powerful machines (e.g., VMs with <= 4GB of RAM) frequently fail servo builds due to the OOM killer because right now we can sometimes have N_CORES clangs running building SpiderMonkey at the same time that there are N_CORES-1 rustc jobs going. Our current workaround is:
|
FWIW I've thought about this from time to time, and implementation wise the details I believe look like this:
There's a bunch of trickery in For example: fn main() {
for (k, v) in std::env::vars() {
println!("{}={}", k, v);
}
} all: foo
./foo
foo: foo.rs
rustc foo.rs
So, all in all, here's what I think needs to happen:
I think that all subprocesses will also be able to use the jobserver because environment variables and the relevant file descriptors will be inherited, so we should be covered there. |
There are two dimensions to this:
I don't think both need to be addressed at the same time. In fact, the latter is significantly easier than the former, and would be meaningful to have for Firefox. Now, wrt alex's comment about how make makes the jobserver available, it should be noted that the picture is a little more complicated: all:
@echo MAKEFLAGS=$$MAKEFLAGS
@echo MFLAGS=$$MFLAGS
@ls -l /proc/self/fd
+@ls -l /proc/self/fd
While the environment variables are always set, the pipes to the jobserver are only actually passed when the command is preceded with + in the Makefile. And since opening a file will likely pick one of the descriptors passed through the environment (like |
I have an initial version of support for this but unfortunately the situation on Windows is baffling me. It appears there's two make implementations in my MSYS installation locally:
The latter Does anyone else know what's up with the situation here? Is there a way to interact with those "file descriptors" (or whatever they are?) from a separate process? Is this |
An msys installation comes with two copies of various binaries, one of which is for the MINGW environment and the other for the MSYS environment.
This is the MINGW make. It uses native Win32 APIs.
This is the MSYS make. It uses the POSIX APIs, which means it works the same as make on a POSIX system. MSYS has a layer (inherited from cygwin) to translate POSIX into native Win32. Which means this is what handles the fd inheritance. I don't know how it's actually implemented, though. People will unfortunately end up using |
Yeah that was the conclusion I reached as well but what does it even mean to use the POSIX api on Windows? Surely that means there's basically just some translation layer, but what's it translating to? If a file descriptor is in a child process what does that mean? Is there a handling floating around we can identify and use? |
cf. what I wrote :) there's a translation layer inherited from cygwin. Following links around from the msys site, it seems to be https://github.com/alexpux/cygwin . |
I've sent a PR for this in #4110 |
This commit adds a GNU make jobserver implementation to Cargo, both as a client of existing jobservers and also a creator of new jobservers. The jobserver is actually just an IPC semaphore which manifests itself as a pipe with N bytes of tokens on Unix and a literal IPC semaphore on Windows. The rough protocol is then if you want to run a job you read acquire the semaphore (read a byte on Unix or wait on the semaphore on Windows) and then you release it when you're done. All the hairy details of the jobserver implementation are housed in the `jobserver` crate on crates.io instead of Cargo. This should hopefully make it much easier for the compiler to also share a jobserver implementation eventually. The main tricky bit here is that on Unix and Windows acquiring a jobserver token will block the calling thread. We need to either way for a running job to exit or to acquire a new token when we want to spawn a new job. To handle this the current implementation spawns a helper thread that does the blocking and sends a message back to Cargo when it receives a token. It's a little trickier with shutting down this thread gracefully as well but more details can be found in the `jobserver` crate. Unfortunately crates are unlikely to see an immediate benefit of this once implemented. Most crates are run with a manual `make -jN` and this overrides the jobserver in the environment, creating a new jobserver in the sub-make. If the `-jN` argument is removed, however, then `make` will share Cargo's jobserver and properly limit parallelism. Closes rust-lang#1744
Add a GNU make jobserver implementation to Cargo This commit adds a GNU make jobserver implementation to Cargo, both as a client of existing jobservers and also a creator of new jobservers. The jobserver is actually just an IPC semaphore which manifests itself as a pipe with N bytes of tokens on Unix and a literal IPC semaphore on Windows. The rough protocol is then if you want to run a job you read acquire the semaphore (read a byte on Unix or wait on the semaphore on Windows) and then you release it when you're done. All the hairy details of the jobserver implementation are housed in the `jobserver` crate on crates.io instead of Cargo. This should hopefully make it much easier for the compiler to also share a jobserver implementation eventually. The main tricky bit here is that on Unix and Windows acquiring a jobserver token will block the calling thread. We need to either way for a running job to exit or to acquire a new token when we want to spawn a new job. To handle this the current implementation spawns a helper thread that does the blocking and sends a message back to Cargo when it receives a token. It's a little trickier with shutting down this thread gracefully as well but more details can be found in the `jobserver` crate. Unfortunately crates are unlikely to see an immediate benefit of this once implemented. Most crates are run with a manual `make -jN` and this overrides the jobserver in the environment, creating a new jobserver in the sub-make. If the `-jN` argument is removed, however, then `make` will share Cargo's jobserver and properly limit parallelism. Closes #1744
These environment variables are now set by rust (rust-lang/cargo#1744). This interferes with the NMAKE command on MSVC.
These environment variables are now set by rust (rust-lang/cargo#1744). This interferes with the NMAKE command on MSVC.
Make's jobserver is described in http://make.mad-scientist.net/papers/jobserver-implementation/
This allows us to prevent make builds from launching too many jobs.
The text was updated successfully, but these errors were encountered: