15 ms·
Rust – Faster compilation with the parallel front-end in nightly
- rowanG077 3y agoI'm not sure this is an interesting direction. Isn't Rust compilation already highly-parallel at the file level? Sure if a single file compiles faster that nice. But won't this steal resources from the top-level file parallelism? I find it quite concerning that there are no numbers given for that.
- goldsteinq 3y agoIt’s not. Rust compilation is currently parallel at the _crate_ level (i.e. one crate is one translation unit). Speeding up compilation of large crates could lead to nice speedups. > But won't this steal resources from the top-level file parallelism? It won’t. rustc uses jobserver protocol to coordinate parallelism with cargo, so the total amount of threads doing compilation of the whole project doesn’t exceed CPU count.
- jakubadamw 3y agoToday, Rust compilation is parallel in the front-end at the crate level, not file or even module level. Large crates will therefore not benefit from parallelism, and splitting a large crate into smaller ones comes with its own costs too. This, however, doesn't apply to the code generation phase with LLVM which is already parallelizable at the codegen unit level (the number of codegen units is configurable), but that's the “back-end”, whereas this new parallelization applies to the “front-end” of the compiler.
- littlestymaar 3y ago> Today, Rust compilation is parallel in the front-end at the crate level, not file or even module level. Large crates will therefore not benefit from parallelism, Sort of, it's managed at the crate level and not file or module indeed, but the compiler then splits crates into smaller chunks called “codegen units”. See: https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units https://doc.rust-lang.org/rustc/codegen-options/index.html#c... > This flag controls the maximum number of code generation units the crate is split into. […] When a crate is split into multiple codegen units, LLVM is able to process them in parallel. […] The default value is 16 for non-incremental builds. For incremental builds the default is 256 which allows caching to be more granular.
- afdbcreid 3y agoYour parent already addresses this: > This, however, doesn't apply to the code generation phase with LLVM which is already parallelizable at the codegen unit level (the number of codegen units is configurable), but that's the “back-end”, whereas this new parallelization applies to the “front-end” of the compiler.
- mattrighetti 3y ago> Existing interprocess parallelism > When you compile a Rust program, Cargo launches multiple rustc processes, compiling multiple crates in parallel.
- mort96 3y agoAnyone who has tried to compile Rust projects on a system with many cores while running htop could tell you that it spends a whole lot of time using only a few cores. Remember, Rust is not like C where the interface definitions (header files) exist on disk so all files can be compiled completely independently.
- the_duke 3y agoDid you read the post?
- deleted 3y ago[deleted]
- exxos 3y ago[dead]
- darthrupert 3y agoI've been away from doing Rust semi-actively for a few years, and have been working in other environments like python and Typescript. Now I tried it for a project for a while again and the compilation speed is pretty much instant. It's always great when things get better, but things are pretty damned good already. Also, these days it's possible to use cheat codes aka ChatGPT to flounder through almost all the difficult Rust problems that might have been show stoppers a few years ago. It's looking pretty great on that side of the fence.
- mpartel 3y agoCompilation times depend very heavily on the amount/size/complexity of dependencies.
- nicoburns 3y agoAnd also processor speed.
- the_duke 3y agoAnd on having a fast CPU, RAM and disk. It makes a huge difference. For what it's worth, I'm working on a project with about 1000 dependencies and incremental debug build time is about 4 seconds on my laptop. That's already pretty good.
- epage 3y agoI know you said 4s is good but have you tried changing the linker? Number of dependencies likely won't affect incremental build times except for linking and replacing it might offer some good gains for incremental builds.
- the_duke 3y agoOh that time is already with mold. Default linker is quite a bit slower.
- darthrupert 3y ago
- papaver-somnamb 3y agoWhat I find most impressive about Rust is the marketing. It's not the language itself. It's not the safety and other attributes. And it certainly can't be the adoption (currently low % according to StackOverflow [0]). It's how hyped Rust is. It's how effusive every blurb and sound bite seems to be. Glowing articles frequently make the front page of HN. Famous for penetration into Linux kernel development. What is this mechanism? Who is behind it? Is this veritable storm of hitting me on the head with Rust-this-Rust-that coordinated behind the scenes by some powerful entity? A hyperactive grassroots cheerleader squad? Does it infect C/C++ programmers who've dared to sample it once, turning them into noisy advocates, a la addictive drugs or parasitic fungi? Is Rust merely the It-Thing at the moment that people are mimetically/socially driven to latch onto? We didn't see this with Lua, Ruby (that was mainly RoR anyways), Python, Swift, C#, certainly not newer-spec C and C++, or any of the others, even Java back in the day. I don't know Rust, maybe it's deserving of the adulation. But I gotta say, the Rust marketing machine is one of the most superlative campaigns in IT I've ever seen. [0] https://survey.stackoverflow.co/2022#most-popular-technologies-language https://survey.stackoverflow.co/2022#most-popular-technologi... Footnote: Some folk seem to be taking offense at my question where none is offered. I'm not for or against Rust, merely ambivalent & curious. Seen many of these waves come through, Rust is definitely the current wave, and the biggest so far! That is something I wish to learn from.
- dijit 3y agonew systems languages are much more rare than new scripting languages, and the focus on usability of the surrounding toolchain makes it a particular darling for anyone who touches it. The other arguments (memory safety et al.) are sort of on the side imo; I really enjoy writing, reading and running rust because the developer experience is just so solid. When I say "developer experience" I mean the crates system and cargo, not necessarily the language itself (which I find a bit ugly to be frank).
- ReleaseCandidat 3y ago> new systems languages are much more rare than new scripting languages No, and have never been. C and later C++ are (were) just _that_ prominent, that most people never heard of the alternatives (except for Pascal and/or ADA, Objective-C and maybe D). Nowadays there is Zig (most people have heard about that, I guess), Carbon, Cppfront, Odin, Jai, Vale, Austral (and some more I've forgotten about).
- ReleaseCandidat 3y ago> In multi-threaded mode there are some known bugs, including deadlocks. If compilation hangs, you have probably hit one of them. Ok, I guess I wait a bit longer before using `-Z threads` ;)
- nu11ptr 3y agoNice! One thing I have noticed is that, unlike the library crate ecosystem, my binary crates by default would be large and monolithic (I now divide into multiple library crates). This means toward the tail end of compilation not only can compilation not be parallelized, but also that the largest crates tend to serialized, so this is a very welcome change!
- insanitybit 3y agoI know it's early days on this, but compilation speed is the downside to Rust IMO. Having worked in a Rust monorepo, my number one complaint was compilation speed. It made CI/CD more expensive and it could really slow down dev time if we needed to remove the cache (happened sometimes - not cargo's fault, actually it's a docker bug, but still). Glad to see this progress.
- lucasyvas 3y agoAs someone who has only done small projects in Rust, I'm curious how many LoC are we're talking? And were you splitting your project into crates where it made sense?
- eminence32 3y agoOne thing I've observed is that every smallish projects (~10k LoC) can take a while to build if you're working on slow network filesystems. When using local disks, a 10k LoC project takes ~5 seconds to build When using network FS, the same project takes ~23 seconds to build
- the8472 3y agoThat doesn't seem particularly surprising. Lots of software is slow when your storage is slow.
- eminence32 3y agoYou're right that some slowdown is expected, but for me personally I hadn't realized how bad this particular FS was, nor had I expected how much it impacted build times
- lolinder 3y agoWouldn't this be true of any compiler? Do other compilers have optimizations that avoid excess disk usage when on a slow file system?
- codeflo 3y agoIs there a way to make it use the number of CPU cores instead of hardcoding a fixed value into a config file that’s used on different machines?
- wonrax 3y agoRUSTFLAGS environment variable, it's mentioned in the post too: > $ RUSTFLAGS="-Z threads=8" cargo build --release
- epage 3y agoKeep in mind, this is still an experiment and is restricted to nightly, so its not configured for general use. Id expect the stabilized default to be number of cores. No idea where this effort is at but at one point they were going to use jobserver to coordinate across cargo's rustc invokations at which point cargo's job count will be used which defaults to number of cores (and supports counting down from that with negative numbers.
- lights0123 3y agoBecause it uses the jobserver protocol which Cargo initializes to the number of cores by default, I'd imagine you could set the new flag to some unreasonably high number (e.g. 10000) and it should limit usage to free cores.
- sylware 3y agoCome on, could we get minimal bootstraping rust compiler instead of 350MB on x86_64 linux? Namely, the rust-written compiler executable to generate simple .o ELF object and that's it. And bootstraping: namely a static PIE ELF executable. Rust has the opportunity to be serious, not lost like gcc.
- the8472 3y agoprocmacros are loaded as dylibs, so dynamic linking is necessary. if you want a bootstrap procedure take a look at what guix does, they go through mrustc.
- sylware 3y agoI don't want all that kludge, a simple machine code generator, a rust-written rust compiler, on x86_64 linux, a static PIE ELF executable. How hard can it be? I give it a rust compiling unit and it outputs a ELF relocatable object.
- boredumb 3y agoHooray! I used rust eons ago when even toy examples were fairly slow to compile and after coming back recently I've started to really love rust and have been using it when ever possible without even thinking about compile times, but I do have one project that has grown a bit and I started getting deja vu when it takes 5+ seconds to compile a simple change I start thinking about not saving things to trigger my analyzer until I work out some other things to not try to work them out while my laptop turns into an aircraft engine. Very exciting as this is the one pain point for me personally so any and all progress is much appreciated
- denysvitali 3y agoFinally!!
- sfink 3y agoStupid question: does the back-end have to wait for the front-end to do borrow checking? If so, why? (I'm not suggesting that it's doing anything wrong. I'm just wondering if borrow checking establishes invariants that the back-end depends on for more than correctness, such that you couldn't do speculative back-end work that you would discard on a borrow checking error.)
- hobofan 3y agoWell, there is mrustc[0], a Rust compiler that doesn't include a borrow-checker, so it's possible to compile (at least some versions of) Rust without a borrow checker, though it might not result in the most optimized code. AFAIK there are some optimization like the infamous `noalias` optimization (which took several tries to get turned on[1]) that uses information established during borrow checking. I'm also not sure what the relation with NLL (non-lexical lifetimes) is, where I would assume you would need at least a primitive borrow-checker to establish some information that the backend might be interested in. Then again, mrustc compiles Rust versions that have NLL features without a borrow-checker, so it's again probably more on the optimization side than being essential. [0]: https://github.com/thepowersgang/mrustc https://github.com/thepowersgang/mrustc [1]: https://stackoverflow.com/a/57259339 https://stackoverflow.com/a/57259339
- pornel 3y agoI don’t think you need lifetimes for the noalias optimization, because it’s a guarantee of &mut, every single one of them, not their exact lifetimes. Also the slowness is not because of lifetime checking. `cargo check` is very fast compared to `cargo build`.
- pests 3y agoThe borrow checker determines the set of valid programs. mrustc gets past not having a borrow checker by compiling invalid programs that would have otherwise had compiler errors. This, at best, results in runtime segfaults etc. Just like you don't need to validate syntax if you just assume you're only ever fed valid syntax. Nothing wrong with that, just want to clarify for people.
- 3y ago
- Vecr 3y agoIs there any way I can disable the parallel compiler option without rebuilding the compiler? I don't need to use it (I have codegen units set to 1 anyway), and it's possible it's causing an ICE that I don't want to debug. To be clear, I know it's set to 1 thread by default, but I want it all the way off.