Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
LLVM 13's new pass manager improves Rust's compile times by up to 20% (twitter.com/ryan_levick)
61 points by paavohtl on Sept 29, 2021 | hide | past | favorite | 18 comments


Even though this is awesome as it affects everything using the LLVM toolchain, I fear that for Rust, percentages won't suffice. Rust needs multi X speedups.

Rusts zero cost abstractions aren't free at all, you pay with compile time, and they ain't cheap.


Percentages turn into multiple X-es over time, as they build on each other. The compiler has gotten multiple X-es faster than it was at 1.0, via repeated and persistent work on those small percentage patches.


There is a fundamental limit to that though, based on how complex rust is in a multitude of domains. From macros to types, all that stacked complexity makes amdahls law eat you alive.

And it has real world implications too. Documentation could be vastly better if it could reference traits across package boundaries. With a "slow" compiler that is simply not feasible, the act of finding the relevant packages is NP hard in itself and multiplied with the compile time.


> Documentation could be vastly better if it could reference traits across package boundaries

Could you clarify what you mean by this? As far as I know the vast, vast majority of rustc's compile time is spent on code generation (hence the massive speedup from an LLVM update), and everything else is relatively well optimized.


When you push a package to crates.io, docs.rs will do a static analysis of this package and its dependencies and try its best to create meaningful links between the traits and implementing types.

The issue is that it is quite common to have trait definitions in one create being used by other ones. Often this is even done when a single library gets too large e.g. tokio, one incentive for splitting being compile time.

However since analysis happens upwards the dependency tree, nodes further up the chain won't know what's below them and can't link to them.

You'd essentially have to do whole creates.io analysis, and while in theory that's feasible with static analysis, rusts type system is so powerful that you have to run a lot of the compiler to get meaningful "static" information, and thus would need a faster compiler/type checker.

(Ranty tangent ;) : I'm not sure if static analysis is even feasible with rusts massive complexity, and implementation defined behaviours. I mean nobody actually _knows_ if rust is save, it's just generally assumed. The closest thing to a formal proof that I know of is Oxide (https://arxiv.org/abs/1903.00982). The rust "commitee" tends to defer so many descisions into the future as to not accidentally paint themselves into a corner, that the spec is just the code and a bunch of thoughts in heads, RFCs, and github issues.

Hoare comes to mind: There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.)

So the "classes implementing this interface" which exists in the Java world, and which is really useful for exploring an API doesn't really exist for crates (at least not automatically).

It creates these Trait islands, where you can navigate to, but not away from.


I'm not convinced that the problem is all that more difficult than for Java. Rust is pretty strict about requiring either the trait being implemented or the thing the trait is being implemented for to be defined in the declaring module. Additionally, Rust is conservative in requiring "forall" trait implementations to never come into conflict. The compiler does not allow multiple "forall" trait implementations if it is possible for code not yet written to satisfy both implementation requirements.

The bigger issue is that the number of implementers for certain traits is going to be huge due to broad "forall" implementations. Instead of doing that, you can just list out actual implementations and condense the "forall" implementations into one node. In practice, I have found it pretty easy to figure out what code implements what interface, particularly if you build the docs for your own crate.


> I'm not convinced that the problem is all that more difficult than for Java.

Turing complete type system + turing complete macro system => you gotta run (compile) the thing to see what it does or is (Rice's theorem).

For a language like Zig, which also has a turing complete compilation step, due to it's comptime sytem, this limitation also applies, but Zig mitigates this with insanely quick compile times. So for these multi project analysis to work you either need to have a very syntax heavy language (Java) or a fast compiler (Zig). Although the latter doesn't really have that strong of a type system in practice (though I think you could implement a datalog engine like rust has in comptime and do arcane type magic then ;) ).

If you compile the packages yourself you can get rustdoc to provide you with the correct links, but then we're back to the manual labor part which I'd like to remove in order to get eco-system-wide docs.


Java's type system is also turing complete: https://arxiv.org/abs/1605.05274


Do you know that the reason for this is that the compiler is too slow, or are you making an assumption? I agree that this would be a good feature to have in docs.rs, though it could potentially make the docs very messy to read if there was no way to choose which crates to show together.

I know that Rustdoc can do this; see SWC's docs for example: https://rustdoc.swc.rs/swc_ecma_visit/trait.Visit.html#imple...


Came out of a discussion with Joshua Nelson a.k.a. rustdoc team lead. (The compiler being too slow for this, not the ranty bits ;) And yea, rustdoc supports this via manual annotations afaik.

I stumbled upon this because somebody had forgot to add the annotation, as these things happen when they're done manually.


That is not what Bjarne Stroustrup means with zero cost abstractions.


I'm aware that it's zero-runtime-cost-abstractions, but that's not what sticks with non system devs when they read rusts "marketing material" (blog posts, talks, e.t.c.)


Fair enough.

In regards to your point, using other backends other than LLVM and cargo having full support for binary libraries would solve a big part of the compilation time story.

In spite of its fame, C++ builds can be made relatively fast when using binary libraries, and even on its baby state, one can already notice some difference with modules workloads in Visual C++.

So I am still hopeful that Rust will improve its compilation story.


Binary libraries are fully supported in Rust, via the C ABI. You can provide a higher-level interface via a wrapper crate. Meanwhile C++ is stuck with 'ABI stability' practices that prevent all sorts of otherwise desirable changes in C++ library code, because they would introduce breaks in binary compatibility.


> Binary libraries are fully supported in Rust, via the C ABI. You can provide a higher-level interface via a wrapper crate.

I've never seen this in the wild and to be honest, it seems massively inconvenient to write a library, create a C-compatible interface for it (meaning you lose out on most benefits of Rust's type system), and then write a wrapper for said C-like API to regain type/memory safety and abstraction power. The killer is that you lose the ability to use traits in the interface between, which idiomatic Rust heavily relies upon.


That isn't what I was mentioning, I don't want to write C ABIs to use Rust libraries.

Those stability practices is what allows me to use Qt, VCL, MFC, .... without rebuilding the world every time I need to start something new with them.

It also allows several companies to sell C and C++ libraries, that wouldn't have done otherwise.


I wonder if it's time to move past that original meaning, or perhaps invent a new catchy term to describe the problem. I'm reminded of this CppCon talk

https://youtu.be/rHIkrotSwcc?t=888


Exactly, I always bring this up with the rust community, zero cost abstractions feels more like a sales pitch




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: