Live data from Hacker News

Incremental Compilation

blog.rust-lang.org

21–30 of 74 posts

Re: Incremental Compilation

#21
post #7

From an uninformed distance this looks a bit underwhelming: initial builds are slower, incremental builds are not _that_ much faster, and build outputs are no longer deterministic functions of just the build inputs (which is useful for example for distributed build systems).

Why does it become non-deterministic?

Re: Incremental Compilation

#22
post #8

How does this differ from what make files have been doing for decades?

Makefiles work at the file level.

This works at the abstract syntax tree level.

If you change a file that many other files depend on Makefiles will recompile all those files. This approach will only recompile the parts affected by the change in AST which will likely be significantly less.

Re: Incremental Compilation

#23
post #19

Earlier quoted context omitted.

> I don't split up my code manually for the compiler, I do it for the humans, being compiler friendly is just a pleasant side effect. There is no human benefit to having to copy and paste function signatures—and worse, the bodies of functions you want to be inlined, including all templates—into header files. There's also no benefit to having the compiler parse hundreds of KB of header files over and over and over aga…

I don't disagree on the header files, no sane language designed today would include that. > Java (production implementations used in practice) performs whole program optimization via its JIT. It's nice for Java, but that isn't how Rust works. Whole program optimization isn't generally something you want on dev builds, which is where incremental compilation is useful. For a production build why wouldn't you do a full…

> Whole program optimization isn't generally something you want on dev builds, which is where incremental compilation is useful.

By "whole program optimization" I also include things like generic/template instantiation. Whenever you use, say, a HashMap, you have to recompile the implementation of the HashMap specialized to the size, alignment, destructor, etc. of types you're using with it.

> For a production build why wouldn't you do a full rebuild anyway?

When I profile apps written in Rust, it's important for me to be able to get good turnaround time on optimized builds.

Re: Incremental Compilation

#24
post #7

From an uninformed distance this looks a bit underwhelming: initial builds are slower, incremental builds are not _that_ much faster, and build outputs are no longer deterministic functions of just the build inputs (which is useful for example for distributed build systems).

Why does it become non-deterministic?

I think the point is that the work done is not deterministic based on just the file inputs. Specifically, it has to pull in the external state of what the previous compile did.

I would hope that the actual output is deterministic based on the inputs. That is, changing function C in a file that has A, B, and C should be the same as a fresh compile of the same file. Even if the actual work that is done is different.

Re: Incremental Compilation

#25
post #6
post #3

Nice to see it. Incremental compilation is one of those things that production compilers have but research languages usually don't have. You only need it when you have a lot of code, but then you really need it.

Production compilers often don't have it either. (Having to split up your code manually into separate .cpp [or what have you] files doesn't qualify as incremental compilation—that's just separate compilation. Incremental compilation is when the compiler automatically figures out what needs to be recompiled, even when all you hand it is a big blob of code that hasn't been manually split up by a human in any way.)

If you have a single source file that's big enough for the compiler to bog down on it, then either that compiler is beyond ridiculously slow, or you need to refactor.

Re: Incremental Compilation

#26

Earlier quoted context omitted.

Splitting up code into headers and sources also helps keep interfaces separate from implementations. It allows one to not only read just the header for the full interface, but it also allows one to distribute the implementation in binary form and the interface in source form, which is important for companies.

Except for inlineable functions and templates in C++—which become a greater and greater fraction of code the more "modern" your C++ gets. Not to mention that the size of your instance variables leaks into your public interface unless you manually heap allocate and use the pimpl idiom. In any case, Rust stores the interfaces to libraries in serialized binary form (including documentation, following a standardized form…

"C++ did it right" seems a separate position from that put forward by the parent comment.

I definitely think there's benefit to being able to view interface as separate from implementation, although that might well be better supported by tooling (editor folding, documentation generation) than manual maintenance - which you seem to be doing well.

I don't know whether there is benefit to being able to edit interface separately from implementation. Probably not much of one, but I could certainly be convinced otherwise.

Re: Incremental Compilation

#27
post #25
post #6

Earlier quoted context omitted.

Production compilers often don't have it either. (Having to split up your code manually into separate .cpp [or what have you] files doesn't qualify as incremental compilation—that's just separate compilation. Incremental compilation is when the compiler automatically figures out what needs to be recompiled, even when all you hand it is a big blob of code that hasn't been manually split up by a human in any way.)

If you have a single source file that's big enough for the compiler to bog down on it, then either that compiler is beyond ridiculously slow, or you need to refactor.

The tricky part is the dependencies between files. This is what C++ uses header files for, but Rust doesn't have those.

Re: Incremental Compilation

#28
post #24

Earlier quoted context omitted.

Why does it become non-deterministic?

I think the point is that the work done is not deterministic based on just the file inputs. Specifically, it has to pull in the external state of what the previous compile did. I would hope that the actual output is deterministic based on the inputs. That is, changing function C in a file that has A, B, and C should be the same as a fresh compile of the same file. Even if the actual work that is done is different.

It is.

Re: Incremental Compilation

#29
Since rust compiles to native machine code (bytes), how does it calculate the starting address of the code? for example, If there is a JMP instruction, JMP takes an address as an operand most likely -- Doesn't the kernel determine the starting address, or is the starting address the address returned by mmap?

Re: Incremental Compilation

#30
post #29

Since rust compiles to native machine code (bytes), how does it calculate the starting address of the code? for example, If there is a JMP instruction, JMP takes an address as an operand most likely -- Doesn't the kernel determine the starting address, or is the starting address the address returned by mmap?

Modern amd64 code is position-independent, so the JMP address is relative.

On other architectures, it's the linker's job to convert symbolic addresses and it can choose all the addresses in one go as it's the final stage producting the executable.

Post reply on HN