Skip to content

Commit 018056a

Browse files
Merge pull request #553 from cevich/groom_rust_cache
Cirrus: Improve caching effectiveness
2 parents 0af413d + c361afa commit 018056a

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

.cirrus.yml

+13-8
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,15 @@ build_task:
5050
# all PRs & branches will share caches with other PRs and branches
5151
# for a given $DEST_BRANCH and vX value. Adjust vX if cache schema
5252
# changes.
53-
fingerprint_key: "cargo_v2_${DEST_BRANCH}_amd64"
53+
fingerprint_script: echo -e "cargo_v3_${DEST_BRANCH}_amd64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"yy
5454
# Required to be set explicitly since fingerprint_key is also set
5555
reupload_on_changes: true
5656
targets_cache: &targets_cache
57-
# Similar to cargo_cache, but holds the actual compiled artifacts. This must
58-
# be scoped similar to bin_cache to avoid binary pollution across cache
59-
# contexts. For example, two PRs that happen to coincidentally change
60-
# and use cache. Adjust vX if cache schema changes.
57+
# Similar to cargo_cache, but holds the actual compiled dependent artifacts.
58+
# This should be scoped to a hash of the dependency-metadata lock file.
59+
# Cirrus-CI will automatically use separate caches for PRs and branches.
6160
folder: "$CARGO_TARGET_DIR"
62-
fingerprint_key: "targets_v2_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_amd64" # Cache only within same tag, branch, or PR (branch will be 'pull/#')
61+
fingerprint_script: echo -e "targets_v3_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_amd64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"
6362
reupload_on_changes: true
6463
bin_cache: &bin_cache
6564
# This simply prevents rebuilding bin/netavark for every subsequent task.
@@ -70,6 +69,7 @@ build_task:
7069
reupload_on_changes: true
7170
setup_script: &setup "$SCRIPT_BASE/setup.sh"
7271
main_script: &main "$SCRIPT_BASE/runner.sh $CIRRUS_TASK_NAME"
72+
cache_grooming_script: &groom bash "$SCRIPT_BASE/cache_groom.sh"
7373
upload_caches: [ "cargo", "targets", "bin" ]
7474

7575

@@ -82,11 +82,15 @@ build_aarch64_task:
8282
architecture: arm64 # CAUTION: This has to be "arm64", not "aarch64"
8383
cargo_cache: &cargo_cache_aarch64
8484
folder: "$CARGO_HOME"
85-
fingerprint_key: "cargo_v2_${DEST_BRANCH}_aarch64"
85+
# N/B: Should exactly match (except for arch) line from build_task (above).
86+
# (No, there isn't an easy way to not duplicate most of this :()
87+
fingerprint_script: echo -e "cargo_v3_${DEST_BRANCH}_aarch64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"yy
8688
reupload_on_changes: true
8789
targets_cache: &targets_cache_aarch64
8890
folder: "$CARGO_TARGET_DIR"
89-
fingerprint_key: "targets_v2_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_aarch64" # Cache only within same tag, branch, or PR (branch will be 'pull/#')
91+
# N/B: Should exactly match (except for arch) line from build_task (above).
92+
# (No, there isn't an easy way to not duplicate most of this :()
93+
fingerprint_script: echo -e "targets_v3_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_aarch64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"
9094
reupload_on_changes: true
9195
bin_cache: &bin_cache_aarch64
9296
# This simply prevents rebuilding bin/netavark for every subsequent task.
@@ -95,6 +99,7 @@ build_aarch64_task:
9599
reupload_on_changes: true
96100
setup_script: *setup
97101
main_script: *main
102+
cache_grooming_script: *groom
98103
upload_caches: [ "cargo", "targets", "bin" ]
99104
# Downstream CI needs the aarch64 binaries from this CI system.
100105
# However, we don't want to confuse architectures.

contrib/cirrus/cache_groom.sh

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
#
3+
# This script is intended to be run from Cirrus-CI to prepare the
4+
# rust targets cache for re-use during subsequent runs. This mainly
5+
# involves removing files and directories which change frequently
6+
# but are cheap/quick to regenerate - i.e. prevent "cache-flapping".
7+
# Any other use of this script is not supported and may cause harm.
8+
9+
set -eo pipefail
10+
11+
source $(dirname ${BASH_SOURCE[0]})/lib.sh
12+
13+
if [[ "$CIRRUS_CI" != true ]]; then
14+
die "Script is not intended for use outside of Cirrus-CI"
15+
fi
16+
17+
req_env_vars CARGO_HOME CARGO_TARGET_DIR CIRRUS_BUILD_ID
18+
19+
# Giant-meat-cleaver HACK: It's possible (with a long-running cache key) for
20+
# the targets and/or cargo cache to grow without-bound (gigabytes). Ref:
21+
# https://github.com/rust-lang/cargo/issues/5026
22+
# There isn't a good way to deal with this or account for outdated content
23+
# in some intelligent way w/o trolling through config and code files. So,
24+
# Any time the Cirrus-CI build ID is evenly divisible by some number (chosen
25+
# arbitrarily) clobber the whole thing and make the next run entirely
26+
# re-populate cache. This is ugly, but maybe the best option available :(
27+
if [[ "$CIRRUS_BRANCH" == "$DEST_BRANCH" ]] && ((CIRRUS_BUILD_ID%15==0)); then
28+
msg "It's a cache-clobber build, yay! This build has been randomly selected for"
29+
msg "a forced cache-wipe! Congradulations! This means the next build will be"
30+
msg "slow, and nobody will know who to to blame!. Lucky you! Hurray!"
31+
msg "(This is necessary to prevent branch-level cache from infinitely growing)"
32+
cd $CARGO_TARGET_DIR
33+
# Could use `cargo clean` for this, but it's easier to just clobber everything.
34+
rm -rf ./* ./.??*
35+
# In case somebody goes poking around, leave a calling-card hopefully leading
36+
# them back to this script. I don't know of a better way to handle this :S
37+
touch CACHE_WAS_CLOBBERED
38+
39+
cd $CARGO_HOME
40+
rm -rf ./* ./.??*
41+
touch CACHE_WAS_CLOBBERED
42+
exit 0
43+
fi
44+
45+
# The following applies to both PRs and branch-level cache. It attempts to remove
46+
# things which are non-essential and/or may change frequently. It stops short of
47+
# trolling through config & code files to determine what is relevant or not.
48+
# Ref: https://doc.rust-lang.org/nightly/cargo/guide/build-cache.html
49+
# https://github.com/Swatinem/rust-cache/tree/master/src
50+
cd $CARGO_TARGET_DIR
51+
for targetname in $(find ./ -type d -maxdepth 1 -mindepth 1); do
52+
msg "Grooming $CARGO_TARGET_DIR/$targetname..."
53+
cd $CARGO_TARGET_DIR/$targetname
54+
# Any top-level hidden files or directories
55+
showrun rm -rf ./.??*
56+
# Example targets
57+
showrun rm -rf ./target/debug/examples
58+
# Documentation
59+
showrun rm -rf ./target/doc
60+
# Internal to rust build process
61+
showrun rm -rf ./target/debug/deps ./target/debug/incremental ./target/debug/build
62+
done
63+
64+
# The following only applies to dependent packages (crates). It follows recommendations
65+
# Ref: https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
66+
# and probably shouldn't be extended beyond what's documented. This cache plays a major
67+
# role in built-time reduction, but must also be prevented from causing "cache-flapping".
68+
cd $CARGO_HOME
69+
for dirname in $(find ./ -type d -maxdepth 2 -mindepth 1); do
70+
case "$dirname" in
71+
./bin) ;& # same steps as next item
72+
./registry/index) ;&
73+
./registry/cache) ;&
74+
./git/db) continue ;; # Keep
75+
*) rm -rf $dirname ;; # Remove
76+
esac
77+
done

contrib/cirrus/lib.sh

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ else # set default values - see make_cienv() below
3232
# VM Images are built with this setup
3333
CARGO_HOME="${CARGO_HOME:-/var/cache/cargo}"
3434
source $CARGO_HOME/env
35+
36+
# Make caching more effective - disable incremental compilation,
37+
# so that the Rust compiler doesn't waste time creating the
38+
# additional artifacts required for incremental builds.
39+
# Ref: https://github.com/marketplace/actions/rust-cache#cache-details
40+
CARGO_INCREMENTAL=0
3541
fi
3642

3743
# END Global export of all variables

0 commit comments

Comments
 (0)