12 ms·
When rustc explodes
- rowanG077 4y agoI recently started a Rust project coming from mostly writing Haskell in my job and oh boy was I surprised. I was expecting long compile times because of the complaints I read about everywhere. But in fact compilation is very speedy. Much, much faster then I'm used to with GHC in fact.
- zamalek 4y agoIt has significantly improved, and I mean significantly, even in the past year alone.
- silverwind 4y agoAccording to https://perf.rust-lang.org/dashboard.html https://perf.rust-lang.org/dashboard.html compile times only have improved by like 5-10% since last year.
- rowanG077 4y agoThat's pretty huge though.
- estebank 4y agoAnd that's only for the aggregate, specific codepaths/code patterns got significantly faster in order to contribute to those numbers. The biggest improvement I see is 68% (bitmaps crate) back in May 25th. https://perf.rust-lang.org/index.html?start=2022-01-01&end=&kind=percentfromfirst&stat=instructions%3Au https://perf.rust-lang.org/index.html?start=2022-01-01&end=&... (takes a while to load, too many datapoints for 6 months at once)
- indiv0 4y ago1. Don't use the `async` ecosystem. 2. Prefer dynamic dispatch to monomorphization (i.e., use fewer generics). 3. Don't use proc macros (i.e., don't depend on the `syn` crate, even transitively). Easy to say; hard to put into practice. But that's all there is to it.
- fasterthanlime 4y ago> Don't use the `async` ecosystem. I want to make it /very/ clear that async isn't to blame at all for the pathological build times described here. It's a bug about traits and lifetimes, both very core concepts of Rust that you deal with even if you stay away from async code. async rust will certainly be more ergonomic once some more improvements land (hopefully later this year), but I don't feel like it deserves all the sighs it's been publicly getting these past few months. (And I /love/ to complain. I've written pieces named "Surviving Rust async interface", "Getting in and out of trouble with Rust futures", "Pin and suffering", etc.) > Prefer dynamic dispatch to monomorphization (i.e., use fewer generics). Unless you hit a pathological case as shown in the article, it tends to not be _that_ bad, especially if you enable `-Z share-generics=y` (unstable still, yet enabled by default for debug builds if I remember correctly). Overall still solid advice - although "use fewer generics" sometimes turns out to be "just turn a big generic type into `Box<dyn Trait>`" (it's not _just_ boxing, that would be `Box<T>`). That's what axum[1] does with all services, and it's never had the compile times issues warp[2] had, for example. > Don't use proc macros (i.e., don't depend on the `syn` crate, even transitively). Good news there, I hear there's some progress on the proc-macro bridge (which improves macro expansion performance) AND "wasm proc-macros". I hope this piece of advice will be completely irrelevant in a year (but for now, it's spot-on. using pin-project-lite instead of pin-project is worth it, for example). [1] https://lib.rs/crates/axum https://lib.rs/crates/axum [2] https://lib.rs/crates/warp https://lib.rs/crates/warp
- vgel 4y agoMy understanding of point #2 is that LLVM may still try to devirtualize the call, which would reduce the performance impact -- is that true for Rust? I know it happens sometimes in C++. Also for proc macros, rust-analyzer seems to struggle with them sometimes as well, so I try to avoid them (outside Serde, which is worth any price) for that reason.
- p1necone 4y agoAFAICT most of the talk about Rust having slow build times is a combination of kneejerk FUD from people that don't like Rust for other ideological reasons, and people that last used Rust when it was much earlier in development. (And also people that have some massive project with hundreds of dependencies that would be slow to build in any language)
- oxff 4y agoI think a bunch of the "rustc compiles slow" talk comes from the misunderstanding of what rustc does. For example, to do the same things as `rustc` but using C++, you need to run external runtime modifying program to check your program for memory errors .. so that extends your C++ "compile time" by fair amount to even begin to match what rustc does.
- pjmlp 4y agoOr use modern IDEs that run the static analysis in the background already spotting many of those issues before the build takes place.
- jstimpfle 4y agoThe question would be for me, can we run those slow-rustc cases faster by skipping the part corresponding to "external checker program"? Or is that part required for each and every build, even after tiny changes or no changes at all?
- oxff 4y agoWell, you are asking about disabling borrow checker here, one of the main selling points of Rust and rustc here so I think that's out of the question. When you do full comparison of what rustc does, and compare it to what you need to do in C++ project to match it, the compile times aren't actually slow since rustc does more with actual guarantees.
- jstimpfle 4y agoBut that was my point, I don't necessarily want to do more. In general I want results faster, and am not willing to trade build speed for more safety checks unconditionally. Having some additional features and checkers is nice, and can even be a life saver, but having to pay a high cost each time I hit compile is not acceptable.
- PoignardAzur 4y ago
- alpaca128 4y agoI don't get the complaints either, especially because so many people seem to treat it as an actually serious issue and not just the meme it is. Yes, many other compilers are faster and produce smaller binaries. But it's not that bad and I get incredible value out of all the checks done by rustc. Incremental builds are reasonably quick and produce excellent error messages. When it comes to efficiency optimizations I see much lower hanging fruits in the web space, some TypeScript projects I'm working on take longer to fully start the dev setup than a fresh optimized Rust build. I hope Bun will make the difference it promises.
- hinach4n 4y agoIt gets pretty bad as your codebase increases. I work on a pretty large Rust project that uses a lot of async, and uses a LOT of static dispatch (mainly because we use a web-server framework called warp). Usually, even after a simple change a simple `cargo check` can take a minute or two on a beefy PC. That said, over time you get numbed to it :D.
- alpaca128 4y agoI can't say much about async because I never really use it. To me it feels like a slightly misleading abstraction/syntax compared to what actually happens, most bugs I introduced in JS backends happened because async/await made the code look more synchronous than it is. Maybe that's just me.
- PoignardAzur 4y agoEvery time I read one of these posts digging into logs and flsmegraphs I think "man, there really should be a simpler way to understand what a compiler is doing when you feed it code".
- fasterthanlime 4y agoAuthor here: I honestly expected it to be much worse. The tracing integration in particular is fantastic - being able to just slap a `#[instrument(...)]` attribute on any function and then be able to filter which spans you want to see is kind of a superpower. That said I think much could be improved, still. I only breezed through the perf/nperf stuff because I've used them before, and through the self-profiling stuff because rustc devs helped me with it. I would've killed for a REPL while I was working on this (or a server architecture so I could write my _own_ rustc queries), and step through them, etc. I like Kate's approach to this[1] - I'd just like something a little more... interactive. What do _you_ think it should look like? I feel like a ton of good ideas come from folks who "simply didn't know it was impossible" (more accurately: haven't been trained to accept to work with subpar tools). I'm excited to try out Pernosco[2] for example, it seems like a much-needed rethink of debuggers. [1]: https://twitter.com/thingskatedid/status/1386077675211526148 https://twitter.com/thingskatedid/status/1386077675211526148 [2]: https://pernos.co/ https://pernos.co/
- PoignardAzur 4y agoThinking "things should be better" was actually part of what led me down the rabbit hole of working on the Druid crate, and then starting my own crates (Panoramix and an unreleased druid fork). > What do _you_ think it should look like? Ideally, I'd want something "browser-devtools-like". Like, you know how, when you hover your mouse over a DOM node in the DOM inspector, Chrome/Firefox will automatically highlight the rendered node on your page? I'd want that for code. Like, I'd want to be able to hover on that `Binder(ProjectionPredicate(...)` dump, and have the IDE highlight the span in the input code of the `where clause` this matches. (Or like, not in the input code, but in a buffer showing one of the intermediate representations.) Other things I'd want: - Being able to alt-click on the `Binder` log and open a page showing Binger's documentation, instead of having to ctrl+shift+f it in the code. - Being able to select a value I don't like, and jump to the call stack that generated that value, inspect variables in that call stack, etc. - Being able to hot-reload and execute spans with different parameters. Eg I'd want to be able to rewrite a function, and have it be recompiled on the fly, and called with the same parameters as before, and see the changes and new logs propagate. Of course this only works if the function is pure and part of a pass system; the idea being that the IDE would cache the previous passes. The document I've seen that best encapsulates what I'd want is "Learnable Programming" by Bret Victor: http://worrydream.com/#!/LearnableProgramming http://worrydream.com/#!/LearnableProgramming > I'm excited to try out Pernosco I really liked Pernosco when I first saw it! I haven't had the occasion to use it yet, but I really like the principles behind it. I've also heard good things about Jaeger, and the UI looks good in your screenshots. I might try to use it if I ever give working on rustc another try.
- svnpenn 4y ago> The crux of the problem is "gee grandma, what big types you have there", because... essentially, tower is a couple of important traits. > And the basic idea is "oh shit we don't have async trait methods" (hence the Future associated type) but also "backpressure is love, backpressure is life", by way of the poll_ready method. I really don't like this guys style of writing. It seems like the bones of the article are interesting, but then they slap like three layers of meme talk, irony and sarcasm, and it just ruins the read for me. It reminds me of TARS humor setting. It doesn't need to be zero, but its currently at like 98, can we turn it down some?
- aaaaaaaaaaab 4y agoIt's the kind of humor that usually not even the author finds funny. They just learned that this is how "funny" people talk.
- vgel 4y agoIt's fair to not appreciate the humor oneself, but this is a really unfair judgement / assumption of the author's intent.
- game-of-throws 4y agoThe emperor has no sense of humor?
- fasterthanlime 4y ago> but its currently at like 98 Come on now. There's two chasms between "an academic paper", my blog, and "a blog with minion/the office reaction GIFs". The amount of humor is finely-tuned so that it's not /too/ distracting from the actual technical topic at hand (of which there's always one, I'm not a sit-down comic), but it also filters out folks who'd rather focus on the form than the content / take themselves too seriously. Looks like the net caught you! Hi!
- staticassertion 4y agoI would really like to see more minion gifs in your posts
- ArrayBoundCheck 4y agoRough. It seems like there's a lot of poor engineering in the compiler :( I almost wonder if the new gcc backend will be better but then I remember clang is significantly faster than gcc
- dymk 4y agoPoor engineering? They’re effectively implementing a constraint solver. It’s not even semantically buggy, it’s just a perf bug. Compilers are hard.
- DC-3 4y agowarp is quite a nice framework but it has a really bad tendency to blow up compiletimes in my experience. I think for non trivial projects in the future I will prefer something else because it can be a real sore spot.
- spoiler 4y agoWarp is really cool from a fun "look what we can do with the type system" way, and I enjoyed it for a pet project. However, when we used it at work, it quickly became incredibly annoying in a larger team. My main gripe with it is it's unusual (which o previously thought was cool) way of building the routing tree, which impedes visibility in code. I.e. I can't just grep for a route; I need to walk the tree to find a handler. There's also a few other things it doesn't handle that well, like streams. However, you're right that the compile times are an issue too. I much enjoy Axum now though, and whose API slightly reminds me of Bevy's ECS; in its practical use of the type system to achieve ergonomics.
- nbittich 4y agoI don't see how rust will manage to fix async await, unless making a v2 of the language. While working with sync rust is often a very pleasant experience, everytime I used async await was awful. To the point that I avoid using rust for web /networking stuff, any other option is better. It's also very discouraging to read some people telling there's no issue with async await. Of course if you use a thousands of libraries (that are more or less hacks), and never use trait and generics, it's probably a decent experience half of the time I'd say. It's something I've only encountered with rust community, in Java when a feature sucks, we just say it sucks. Even the architect that approved it will say it sucks.
- mleonhard 4y agoYou can use Servlin to make an HTTP server with sync Rust. I made it. https://crates.io/crates/servlin https://crates.io/crates/servlin
- nynx 4y agoCould you be more specific about what’s bad about it?
- dnsco 4y agoYesterday it took me and my pair like 3 hours to figure out how to iterate over a vector of things asynchronously. Eventually we found collect'ing into a FuturesUnordered, after already implementing a repeated collect into vector of futures and then futures::join_all them. The error messages we encountered while going through this were not the amazing one's we're used to from sync rust, these were... cryptic, to say the least.
- estebank 4y ago> The error messages we encountered while going through this were not the amazing one's we're used to from sync rust, these were... cryptic, to say the least. Please file tickets when you encounter these. A lot of the "great errors in rustc" are by their nature reactive: we need to see what people try when they hit corners that haven't gotten as much love. async/await uses multiple somewhat advanced features under the covers that have a tendency to provide either verbose or confusing errors. We're slowly improving them, but having good examples of real world cases is incredibly useful to speed up that process. This is what allows us to have extra information with recommendations.
- a_t48 4y agoI sympathize with this, after tracking down C++ performance issues (though not going as far as recompiling the compiler).
- pjmlp 4y agoI also did my share of optimizing C and C++ builds, however while the worst case can turn into hours, in most places it isn't as bad, because the communities do embrace binary libraries instead of compiling all third party dependencies (or other in-house teams) from scratch.
- steveklabnik 4y ago... yet that's still about initial build times, because once you've built your dependencies, you don't build them again.
- pjmlp 4y agoExcept building the same crates multiple times across the depedency graph. Additionally, from my point of view, not caring about initial build times is a crappy development experience, versus what is offered by apt/yum/NuGet/vcpkg/conan.
- a_t48 4y agoAll of the packages I'm using for my most recent project (https://github.com/zig-for/snfm/blob/main/vcpkg.json https://github.com/zig-for/snfm/blob/main/vcpkg.json) required building on machine. Takes about an hour and doesn't run in parallel (now there's a good PR for someone...). Vcpkg packages _can_ be distributed in binary form, it just doesn't happen.
- stephc_int13 4y agoI am not super familiar with the Rust syntax, but simply glancing over it made me puke. How is that considered good design? It seems even worse than C++ nightmarish Boost/templates meta-programming. Powerful, maybe, but what about readable?
- dymk 4y agoHaving written a huge amount of heavily templated C++ and a moderate amount of heavily generic’d Rust, I prefer Rust any day. No more ‘typename’ for me thank you.