-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Allow restricting the number of parallel linker invocations #9157
Comments
I believe this would also be useful for people using |
I have no idea if this would be practical, but could cargo automatically monitor memory usage to adjust how many concurrent threads to use? |
I've managed to work around this by enabling swap. Linking time did not suffer visibly. On Ubuntu, I followed this guide. |
Proposed SolutionAdding Here what would help look like (
|
@rustbot claim |
@weihanglo see also #7480 |
FWIW, Cabel community had a discussion a while back: haskell/cabal#1529 |
Potentially the unstable rustc flag |
As this is focusing on the problem of OOM, I'm going to close in favor of #12912 so we keep the conversations in one place. |
FWIW, setting Something we might want to keep an eye on in rustc: rust-lang/rust#48762 |
I suppose, although this is a very specific problem and I'm doubtful that the generic mechanisms being discussed in that issue will really help address it. |
FWIW, there is a |
rust-lang/rust#117962 has made into nightly. It could alleviate the pain of linker OOM to some extent. |
I suspect this will make performance much worse in the average case, unfortunately. |
i think this can be closed, as it is the linkers business to not run out of memory. e.g. mold does this, see rui314/mold#1319 via its |
For something like that, jobserver support in a linker would be a big help so we can coordinate across rustc and the linker for how many threads are available to use. That also only focuses on number of parallel threads and not actual memory consumption. Like with threads, likely any solution coordination will be needed between links and rustc / cargo |
what I am seeing with the move to Linode VMs is essentially this: rust-lang/cargo#9157 rust-lang/cargo#12912 B/c these new VMs have more CPU cores, 16 (new) vs 4(old), compilation is faster however this causes cargo to be overzealous and spawn too many linker processes which consume all of the available memory (on a 64 GB VM) and causes an OOM error forcing the kernel to kill the linker process and causing cargo to fail! Another alternative, which works, is using `--jobs 8`, however that is less optimal b/c it leaves unused CPU capacity and also affects the number of parallel threads when executing the test suite! WARNING: using `--release` is not an option because it breaks tests. The polkadot-sdk code uses the macro defensive! which is designed to panic when running in debug mode and multiple test scenarios rely on this behavior via #[should_panic]! WARNING: we still need the 64 GB memory!
what I am seeing with the move to Linode VMs is essentially this: rust-lang/cargo#9157 rust-lang/cargo#12912 B/c these new VMs have more CPU cores, 16 (new) vs 4(old), compilation is faster however this causes cargo to be overzealous and spawn too many linker processes which consume all of the available memory (on a 64 GB VM) and causes an OOM error forcing the kernel to kill the linker process and causing cargo to fail! Another alternative, which works, is using `--jobs 8`, however that is less optimal b/c it leaves unused CPU capacity and also affects the number of parallel threads when executing the test suite! WARNING: using `--release` is not an option because it breaks tests. The polkadot-sdk code uses the macro defensive! which is designed to panic when running in debug mode and multiple test scenarios rely on this behavior via #[should_panic]! WARNING: we still need the 64 GB memory!
In CI at my work, we ran into a situation where rustc would get OOM-killed while linking example binaries:
We were able to mitigate this by using a builder with more available memory, but it's unfortunate. We could dial down the parallelism of the whole build by explicitly passing
-jN
, but that would make the non-linking parts of the build slower by leaving CPU cores idle.It would be ideal if we could explicitly ask cargo to lower the number of parallel linker invocations it will spawn. Compile steps are generally CPU-intensive, but linking is usually much more memory-intensive. In the extreme case, for large projects like Firefox and Chromium where the vast majority of code gets linked into a single binary, that link step far outweighs any other part of the build in terms of memory usage.
In terms of prior art, ninja has a concept of "pools" that allow expressing this sort of restriction in a more generic way:
The Ninja feature was originally motivated by Chromium builds switching to Ninja and wanting to support distributed builds, in which there might be capacity to spawn way more compile jobs in parallel since they can be run on distributed build nodes, but link jobs, needing to be run on the local machine, would want a lower limit.
If this were implemented, one could imagine a further step whereby cargo could estimate how heavy individual linker invocations are by the number of crates they link, and attempt to set a reasonable default value based on that and the amount of available system memory.
The text was updated successfully, but these errors were encountered: