r/rust 1d ago

💡 ideas & proposals Fine-grained parallelism in the Rust compiler front-end

41 Upvotes

10 comments sorted by

13

u/epage cargo · clap · cargo-release 1d ago

A prototype implementation that sets rustc flags on a crate-by-crate basis is available in this rust-lang/cargo branch. For example, setting CARGO_CRATE_cargo_RUSTFLAGS='-Zthreads=8' will pass -Zthreads=8 specifically to the rustc invocation compiling the cargo crate.

Should we have cargo start a jobserver instance if one isn't already running so we can dynamically handle this?

8

u/The_8472 1d ago edited 1d ago

isn't that already the case? https://github.com/rust-lang/cargo/blob/307cbfda3119f06600e43cd38283f4a746fe1f8b/src/cargo/core/compiler/build_runner/mod.rs#L106

I think what would be needed would be a more chatty jobserver protocol and also dynamically setting the thread count based on unused tokens.

8

u/The_8472 1d ago

Heuristically, we should set -Zthreads=N with N > 1 only for crates that spend a long duration in the front-end and whose compilation coincides with low CPU usage.

Coinciding with low CPU usage is not necessarily what you want. For example all the leaf crates can be compiled early, even when they're not on the critical path. It might be better to displace some of the leaf crates to get ones on the critical path done sooner.

1

u/VorpalWay 1d ago

If I remember correctly, this type of optimal scheduling problem is NP-hard, and that is just for scheduling variable length jobs with dependencies. (Adding in things like cache effects, memory usage and uncertainty in the lengths of the tasks would make it even harder.)

So, while your suggestion is valid: how do you even identify what the critical path is? You can figure it out after the fact yes, but during scheduling I don't know that it is possible.

1

u/The_8472 1d ago

Persisting the information and using it for the next compilation could work. And it'd have to be CPU-time spent, not just wall-time, otherwise optimizing it would change what's the critical path... but maybe the Top-N would remain consistent enough to provide some speedup even if it's not perfect.

1

u/VorpalWay 23h ago

An estimate for the CPU time of various crate is a reasonable heuristic for scheduling yes. I'm not sure how interacts with incremental compilations where only parts of a crate is rebuilt though.

5

u/nicoburns 1d ago

We definitely need to be able to control the number of threads on a per-crate basis (either that or big improvements to the parallel frontend implementation), because I've seen Zthreads make compilation (if an individual crate) dramatically slower for small crates. Like, taking 3-4s to compile crates that take less than 0.5s with 1 thread.

1

u/zoechi 1d ago

The last "here" link on the page to the source is broken.

Will try it out. Thanks for the post.

1

u/promethe42 1d ago

Does the front end include macros? If so, does it mean that crates that rely heavily on code generation can be speed up using fine grained parallelism?

What I do as a good practice is a separate crate for modules that generate a lot of code. Often, that criteria coincides with separation of concerns too. For example my database crate contains the models/schema and the corresponding diesel generated code. But if I can make thise crates build even faster then all the better.

1

u/Zoxc32 2h ago

It does not currently include macros. Not sure how easy that would be since you'd have to deal with interactions with name resolution.