`mach cargo check` is worth listing in Servo's README.md, IMO! Nick
On Sat, Apr 1, 2017 at 4:43 AM, Simon Sapin <simon.sa...@exyr.org> wrote: > If you build Servo a lot you may have noticed that compilation times have > improved over the last few months. This is combination of multiple factors. > > > # Compiler optimization > > Plain old optimization of the compiler’s code. Sometimes a rustup makes > things a bit faster without us changing anything else. For example: > > https://blog.mozilla.org/nnethercote/2016/10/14/how-to-speed > -up-the-rust-compiler/ > https://blog.mozilla.org/nnethercote/2016/11/23/how-to-speed > -up-the-rust-compiler-some-more/ > > > # Limited parallelism > > Cargo can compile multiple crates at the same time, but a crate can only > start after its dependencies are done. And in the default configuration, > compiling one crate only uses one CPU core/thread. Servo’s dependency graph > tends to be narrow near the end, in particular with the script crate that > takes a lot of time to compile. This limits the overall available > parallelism. > > > # Hardware > > CPUs with many cores tend to make each core slower, to manage heat. > Counter-intuitively this can make then worse for compiling Servo. If you’re > spending (your employer’s) money on hardware, I recommend the highest > single-thread performance you can find even if this means fewer cores. > Currently, this is probably Intel’s i7-7700K. (4 cores, 8 threads, 4.2 GHz, > easy to overclock to 4.6 GHz.) > > > # Codegen units > > Compilation of a crate can be roughly split into two phases: analysis and > code generation. The former includes parsing, type checking, borrow > checking, etc. The latter is mostly LLVM. > > rustc added a feature to get parallelism in code generation. With `rustc > -C codegen-units=4` for example, the code to generate is split into four > parts that are given separately to LLVM in threads that run in parallel. > > This makes compilation faster but has a runtime cost: LLVM’s optimizer > only sees one unit at a time, which reduces opportunities for inlining and > other compile-time optimizations. > > Also, only code generation is parallelized, the analysis phase still runs > on a single thread. So Amdahl’s law limits how much speed improvement we > can get with this. > > In Servo we’ve enabled codegen-units=4 by default in debug mode, but not > in release mode. > > https://github.com/servo/servo/pull/14995 > > > # LLVM assertions > > When compiling LLVM (and so when compiling rustc) we can choose to enable > LLVM assertions. There assertions can help find bugs (in LLVM or in rustc), > but they have a runtime cost. (LLVM’s runtime, which is Servo’s compile > time.) This cost can be significant, especially in release mode (where > LLVM’s optimizer does a lot of work). > > Official Rust builds have LLVM assertions enabled in Rust Nightly (to help > catch bug), but not in the beta or stable release channels. > > At our request, the Rust team started making alternative Rust Nightly > builds without LLVM assertions, for some platforms. We’re now using them by > default, except for some of our Continuous Integration builders (in order > to preserve some of the coverage). > > https://github.com/rust-lang/rust/pull/39754 > https://github.com/servo/servo/pull/15559 > https://github.com/servo/servo/pull/15564 > > > # cargo check > > Remember how I said a crate needs its dependencies to be compiled before > it can start compiling? It actually only needs metadata (the results of the > analysis phase), not the generated code. > > Cargo added a `cargo check` command that skips code generation entirely > (except for build scripts and build-dependencies). This saves a lot of time > (I’ve measured up to 5× speed from `./mach clean`), though obviously you > don’t get an executable at the end. Still, it can help for example during a > refactoring: run `./mach cargo check` many times until compiler error are > resolved, and only then run `./mach build` and/or `./mach test-unit`. > > https://github.com/rust-lang/cargo/pull/3296 > https://github.com/servo/servo/pull/14594 > > Follow-up work wanted: add a mach sub-command or option to do this with > geckolib. > > (It would also be nice for rustc to have a mode to write both metadata and > full build, and signal somehow as soon as the former is ready; and have > Cargo start building dependents on that signal while codegen for the > dependencies is still running, increasing overall parallelism.) > > > # Preserving compilation output between CI runs > > Previously, Servo’s Continuous Integration was configured to run `git > clean` at the start of each build, with options such that anything not > checked into the repository was removed. This included the `target` > directory, so each pull request was recompiled from scratch. > > We’ve changed the configuration to preserve files in .gitignore, which > includes the target directory, so that some of the compilation output for > previous builds can be reused. This makes pull requests faster to land > after r+, and try runs faster to give results. > > There is a risk that preserved files could be left by a previous builds in > a broken state, leading to failures that only happen on CI. We’re > monitoring this and will consider reverting this change it this turns out > to be a problem. > > https://github.com/servo/saltfs/pull/611 > > > # Incremental compilation > > Finally, the compiler feature everyone is waiting for. > > In the current default configuration, entire crates are recompiled from > scratch whenever the smallest part of their source or dependencies is > touched. Incremental compilation changes this, caching many intermediate > results so that the next build hopefully doesn’t need to do that work again. > > Incremental compilation in Rust Nightly is currently in "beta". It mostly > works (I’ve been using it exclusively for a couple months) but it’s buggy > on some platforms and the speedups are not as good as one might hope. (Only > code generation is cached, at the moment.) > > It also uses a lot of disk space and memory. The `target` directory in one > of my trees takes 26 GB. (I don’t know if there’s any cache eviction, so > running `cargo clean` occasionally may be needed.) One of our CI builders > with "only" 8 GB of RAM and no swap is unable to build the script crate > with incremental compilation enabled. > > So far we have *not* enabled incremental compilation by default in Servo. > Still, you can try it by copying servobuild.example to .servobuild, then > editing the latter to change `incremental = false` to `incremental = true` > in the [build] section. > > Please send us any feedback! > > https://blog.rust-lang.org/2016/09/08/incremental.html > https://internals.rust-lang.org/t/incremental-compilation-beta/4721 > https://github.com/servo/servo/pull/15390 > https://github.com/servo/servo/pull/15565 > > -- > Simon Sapin > _______________________________________________ > dev-servo mailing list > dev-servo@lists.mozilla.org > https://lists.mozilla.org/listinfo/dev-servo > _______________________________________________ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo