Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking Issue for Incremental Compilation #47660

Open
23 of 32 tasks
michaelwoerister opened this issue Jan 22, 2018 · 7 comments
Open
23 of 32 tasks

Tracking Issue for Incremental Compilation #47660

michaelwoerister opened this issue Jan 22, 2018 · 7 comments
Labels
A-incr-comp Area: Incremental compilation C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC S-tracking-impl-incomplete Status: The implementation is incomplete. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@michaelwoerister
Copy link
Member

michaelwoerister commented Jan 22, 2018

Incremental compilation will soon be available in stable Rust (with version 1.24) but there's still lots of room for improvement. This issue will try to give an overview of specific areas for potential optimization.

Compile Time

The main goal for incremental compilation is to decrease compile times in the common case. Here are some of things that affect it:

Caching Efficiency

The biggest topic for incremental compilation is: How efficiently are we using our caches. It can be further subdivided into the following areas:

Data Structure Stability

Caching efficiency depends on how the data in the cache is represented. If data is likely to change frequently then the cache is likely to be invalidated frequently. One example is source location information: Source location information is likely to change. Add a comment somewhere and the source location of everything below the comment has changed. As a consequence, everything in the cache that contains source location information is likely in need of frequent invalidation. It would be preferable to factor data structures in a way that confines this volatility to only few kinds of cache entries. The following issues track concrete plans to improve the situation here:

Object File Granularity and Partitioning

The problem of object file granularity can be viewed as a variation of "Data Structure Stability" but it is so important for compile times that I want to list it separately. At the moment the compiler will put machine code that comes from items in the same source-level module into the same object file. This means that changing one function in a module will lead to all functions in that module to be re-compiled. Obviously this can lead to a large amount of redundant work. For full accuracy we could in theory have one object file per function - which indeed improves re-compile times a lot in many cases - but that would increase disk space requirements to an unacceptable level and makes compilation sessions with few cache hits much more expensive (TODO: insert numbers). And as long as we don't do incremental linking it might also make linking a bottleneck.

The main goal here is to re-compile as little unchanged code as possible while keeping overhead small. This is a hard problem and some approaches are:

  • Keep using a fixed partitioning scheme but improve the partitioning algorithm
  • Implement an adaptive scheme that reacts to set of changes a user makes
  • It might even be a good idea to write a simulator that allows to test different schemes and then feed it with actual data generated by an instrumented compiler.

Adaptive schemes would require us to re-think part of our testing and benchmarking infrastructure and writing a simulator is a big project of its own, so short term we should look into improved static partitioning schemes:

Another avenue for improvement of how we handle object files:

Whole-Cache Invalidation

Currently commandline arguments are tracked at a very coarse level: Any change to a commandline argument will completely invalidate the cache. The red-green tracking system could take care of making this finer grained but quite a lot of refactoring would need to happen in order to make sure that commandline arguments are only accessible via queries.

Note that this currently completely prevents sharing a cache between cargo check and cargo build.

Avoid Redundant Work

The compiler is doing redundant work at the moment. Reducing it will also positively affect incremental compilation:

Querify More Logic, Cache More Queries

We can only cache things that are represented as queries, and we can only profit from caching for things that are (transitively) cached. There are some obvious candidates for querification:

A more ambitious goal would be to querify name resolution and macro expansion.

Framework Overhead

Doing dependency tracking will invariably introduce some overhead. We should strive to keep this overhead low. The main areas of overhead are:

  • Building the dependency graph during compiler execution
  • Computing query result hashes and dependency node identifiers
  • Loading and storing the dependency graph from/to disk

Another thing that falls into this category is:

  • Efficiency of loading and storing cache entries

The following issues track individual improvements:

We should continuously profile common use cases to find out where we can further reduce framework overhead.

Disk Space Requirements

Build directories of large C/C++ and Rust code bases can be massive, oftentimes many gigabytes. Since incremental compilation has to keep around the previous version of each object file for re-use, plus LLVM IR, plus the dependency graph and query result cache, build directories can up to triple in size when incremental compilation is turned on (depending on which crates are compiled incrementally). The best way to reduce cache size is to reduce the amount of translated code that we need to cache. Solving #47317 and #46477 would help here. MIR-only RLIBs (#38913), which are one way to solve #47317, might also obviate the need to cache LLVM IR at all.

Runtime Performance of Incrementally Compiled Code

Currently delivering good runtime performance for incrementally compiled code is only a side goal. If incrementally compiled code is "fast enough" we rather try to improve compile times. However, since ThinLTO also supports an incremental mode, we could provide a middle ground between "re-compile everything for good performance" and "re-compile incrementally and only get 50% performance".


If you have any further ideas or spot anything that I've missed, let me know in the comments below!

@bstrie
Copy link
Contributor

bstrie commented Oct 16, 2018

Given that the cutoff for Rust 2018 is imminent, is there a summary of the progress on incremental compilation since shipping in 1.24?

@michaelwoerister
Copy link
Member Author

@bstrie Basically all the boxes you see checked in the post above. Note though that the "2018" in the title of the issue does not mean "2018 Edition". It's just a list of things that I thought would be good next steps for incr. comp. to work on this year.

@Xanewok
Copy link
Member

Xanewok commented Jan 5, 2019

A more ambitious goal would be to querify name resolution and macro expansion.

I would like to start working on that in order to slowly work towards enabling end-to-end queries for the RLS. Since last All-Hands a lot of work was spent on parallelizing the queries, so with improved query infrastructure I imagine it'd be a good time to tackle this now.

I realize this needs more design and discussion as to make it actually incremental and more fine-grained but I imagine moving it into whole-crate query and refactoring the session code could be useful.

I'd be more than happy to work on this (most notably starting with name resolution) but I'll also appreciate any mentoring I can get, since I didn't work in the compiler much except for the save-analysis generation.

@nikomatsakis @Zoxc @petrochenkov do you have any immediate plan or vision how this could be tackled now?

@petrochenkov
Copy link
Contributor

petrochenkov commented Jan 5, 2019

@Xanewok

do you have any immediate plan or vision how this could be tackled now?

No plans, I know very little about queries or incremental compilation.

@nikomatsakis
Copy link
Contributor

I would like to start working on that in order to slowly work towards enabling end-to-end queries for the RLS.

I am strongly in favor of this, and I agree with you that a "coarsed-grained" approach is a logical first step. I know that @Zoxc (whom you cc'd) was doing some work here too, but I'm not sure exactly what, and I'm sure @eddyb has thoughts.

Overall I feel like it would be useful to sketch out an overall plan -- maybe it makes sense to try and have an ad-hoc sync meeting to talk over the complications? Pushing backwards from HIR is going to be the biggest challenge, no doubt.

In principle, we could do something like having a hir_map query that just does everything and constructs the hir-map, and then other queries that pull from it -- but I guess another consideration is integrating into the incremental serialization/deserialization infrastructure.

@Xanewok
Copy link
Member

Xanewok commented Jan 12, 2019

maybe it makes sense to try and have an ad-hoc sync meeting to talk over the complications

Sounds like a good idea!

In principle, we could do something like having a hir_map query (...)

FWIW there's already a PR that exposes the precomputed HIR map via hir_map query but the perf's not looking good unfortunately: #57024

@Mark-Simulacrum Mark-Simulacrum changed the title Tracking Issue for Incremental Compilation 2018 Tracking Issue for Incremental Compilation Sep 1, 2019
@jonas-schievink jonas-schievink added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 26, 2019
@pnkfelix
Copy link
Member

Visiting for backlog bonanza. We debated about whether this issue is providing much value as is, versus just closing it (and saying that this is tracked via all the issues with corresponding labels).

But for now we won't do that. We'll leave it open, and just update the label to reflect its status.

@rustbot label: S-tracking-impl-incomplete.

@rustbot rustbot added the S-tracking-impl-incomplete Status: The implementation is incomplete. label May 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-incr-comp Area: Incremental compilation C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC S-tracking-impl-incomplete Status: The implementation is incomplete. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants