Live data from Hacker News

Rust's Huge Compilation Units

pingcap.com

1–10 of 19 posts

Re: Rust's Huge Compilation Units

#2
Its not just a Rust problem, I've run into the same thing in Java and I'm sure it exists elsewhere. The only answer I can come up with is to keep your app cleanly divided into modules. There's some cognitive overhead but its usually worthwhile.

I recently divided a 100k line Java app into 5 different modules and it compiles 4 times faster. The new boundaries have encouraged better code as well. Suddenly we have things like interfaces and IoC. Before, people just stuffed things wherever.

Re: Rust's Huge Compilation Units

#3
>In my experience though projects tend to start in a single crate, without great attention to their internal dependency graph, and once compilation time becomes an issue, they have already created a spaghetti dependency graph that is difficult to refactor into smaller crates.

Maybe there should be a lint for not having modules be mutually dependent?

Re: Rust's Huge Compilation Units

#4
In Haskell two libraries that define conflicting orphan instances can't be linked together. Given the culture around code sharing and crates.io, this would probably be a big problem for Rust. (As I recall I was the first to propose forbidding orphan instances, although at the time I didn't realize they were called that.)

Re: Rust's Huge Compilation Units

#5
post #4

In Haskell two libraries that define conflicting orphan instances can't be linked together. Given the culture around code sharing and crates.io, this would probably be a big problem for Rust. (As I recall I was the first to propose forbidding orphan instances, although at the time I didn't realize they were called that.)

Can you expand on that? What about the culture would make this problematic for Rust specficially?

It does seem like Rust is just enforcing the rough consensus in the Haskell community re: best practices.

Re: Rust's Huge Compilation Units

#6
>In my experience though projects tend to start in a single crate, without great attention to their internal dependency graph, and once compilation time becomes an issue, they have already created a spaghetti dependency graph that is difficult to refactor into smaller crates.

This happened to me too. One important problem to overcome is the orphan rule. This means: you can only implement a trait you own or for a type you own. If both the type and the trait are not in your crate, you are out of luck.

So my first attempt failed utterly. It was very disappointing. You see, by splitting the project in different crates I put one type and one trait in different crates.

After thinking about this problem for a few weeks I accepted that I needed to write wrappers, so called newtypes. But this hurt a lot. I managed to abstract away a lot of the boilerplate by writing macros but still am not very happy about the complexity.

Growing pains.

Re: Rust's Huge Compilation Units

#7

Its not just a Rust problem, I've run into the same thing in Java and I'm sure it exists elsewhere. The only answer I can come up with is to keep your app cleanly divided into modules. There's some cognitive overhead but its usually worthwhile. I recently divided a 100k line Java app into 5 different modules and it compiles 4 times faster. The new boundaries have encouraged better code as well. Suddenly we have thing…

I work with both Java and Rust.

Definitely not the same. With Java, you decide what you want to compile with your build script. You don't need to compile entire application as a single unit. If you have to recompile a lot of code when you only make small modification it is likely because did not use many of available ways to just recompile the classes that you modified.

Also, with Java some optimizations are pushed to runtime. JIT has access to all code running even if it wasn't available at compilation time.

Re: Rust's Huge Compilation Units

#8
post #6

>In my experience though projects tend to start in a single crate, without great attention to their internal dependency graph, and once compilation time becomes an issue, they have already created a spaghetti dependency graph that is difficult to refactor into smaller crates. This happened to me too. One important problem to overcome is the orphan rule. This means: you can only implement a trait you own or for a type…

Funny how, I believe, the terms "orphan" and "newtype" originated in Haskell and were carried over to Rust. Evidence of the functional programming heritage that Rust has, I guess.

Re: Rust's Huge Compilation Units

#9
Just for the record, orphan instances, although possible in Haskell, are regarded as a big problem and something that should be avoided as much as possible. The problem being, you can declare an orphan instance yourself, later discover you need another library, only to discover it implements the orphan instance as well, preventing compilation. Worst case scenario is that the two implementations are semantically different and you no longer have any idea what your code should do.

(Orphan instances in apps are horrible, orphan instances in libraries run the risk of making your whole library unusable.)

As useful as they sometimes are, I can't help feeling Rust made the right call here.

Post reply on HN