Skip to content

Instantly share code, notes, and snippets.

@anna-is-cute
Last active April 21, 2020 21:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anna-is-cute/000456ca646bd502cac0dbddcb8fa307 to your computer and use it in GitHub Desktop.
Save anna-is-cute/000456ca646bd502cac0dbddcb8fa307 to your computer and use it in GitHub Desktop.
Rust and Travis CI cache

Rust and Travis CI cache

Using Travis CI's cache is very useful and helps cut Rust job times way, way down. However, the way that the default caching for Cargo is set up means it will quickly bloat.

Travis currently checks ~/.cargo and target/ for any changes from the current cache after a build. There will always be changes in target/ if the source has changed, which it usually does when a Travis build runs. This means new incremental object files, fingerprints, and build script compilation files are being added to the cache every build.

This also means that your cache will become larger and take longer to upload every build. Eventually, it will reach the point where the default cache upload timeout isn't long enough and the cache will stop being uploaded. At that point, the cache has to be cleared or the timeout extended, both of which aren't real fixes.

The real fix

Assuming your crate name is awesome_crate and has a build script:

# .travis.yml
cache: cargo
before_cache:
  - rm -rfv target/debug/incremental/{awesome_crate,build_script_build}-*
  - rm -rfv target/debug/.fingerprint/awesome_crate-*
  - rm -rfv target/debug/build/awesome_crate-*
  - rm -rfv target/debug/deps/libawesome_crate-*
  - rm -rfv target/debug/deps/awesome_crate-*
  - rm -rfv target/debug/{awesome_crate,libawesome_crate}.d
  - cargo clean -p awesome_crate

If you don't have a build script, remove the build script rm. Tada!

Results

Previously, I cleared my cache and ran a build. The cache was about 450 megabytes. After a day or two of semi-active development, the cache had grown to 555 megabytes.

After implementing the fix, the first build's cache was 341 megabytes. After starting a build manually with no code changes, Travis detected no change in the cache and didn't update it. After adding a small method and making sure it was used, Travis again detected no change in the cache, as we would expect.

Caveats

Updating your dependencies will bloat the cache. I'm looking into ways to remove old, unused dependencies from the target/ directory.

Changing your compiler version (setting rust to nightly in .travis.yml) will cause all dependencies to be rebuilt. This will bloat the cache by a very large amount. A solution is to pin your build to a specific nightly version.

This does remove all incremental objects, so compile time will increase. It went from 30 seconds to 60 seconds for the project I was testing on. YMMV.

@konstin
Copy link

konstin commented Aug 30, 2019

It seems that you now also need to delete target/debug/incremental/common-*, e.g. with rm -rfv target/debug/incremental/{pyo3_pack,build_script_build,common}-*

@codesections
Copy link

Thanks very much for this – it helped me deal with inexplicably long CI build times.

Based on the current Travis Rust docs, it looks like we might also need to add the line - rm -rfv "$TRAVIS_HOME/.cargo/registry/src". Apparently, that line is provided by the default cache configuration and should be manually included if overwriting the default. Is that your understanding as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment