Skip to content

Commit 12555be

Browse files
authored
Stabilize automatic garbage collection. (#14287)
This proposes to stabilize automatic garbage collection of Cargo's global cache data in the cargo home directory. ### What is being stabilized? This PR stabilizes automatic garbage collection, which is triggered at most once per day by default. This automatic gc will delete old, unused files in cargo's home directory. It will delete files that need to be downloaded from the network after 3 months, and files that can be generated without network access after 1 month. These thresholds are intended to balance the intent of reducing cargo's disk usage versus deleting too often forcing cargo to do extra work when files are missing. Tracking of the last-use data is stored in a sqlite database in the cargo home directory. Cargo updates timestamps in that database whenever it accesses a file in the cache. This part is already stabilized. This PR also stabilizes the `gc.auto.frequency` configuration option. The primary use case for when a user may want to set that is to set it to "never" to disable gc should the need arise to avoid it. When gc is initiated, and there are files to delete, there will be a progress bar while it is deleting them. The progress bar will disappear when it finishes. If the user runs with `-v` verbose option, then cargo will also display which files it deletes. If there is an error while cleaning, cargo will only display a warning, and otherwise continue. ### What is not being stabilized? The manual garbage collection option (via `cargo clean gc`) is not proposed to be stabilized at this time. That still needs some design work. This is tracked in #13060. Additionally, there are several low-level config options currently implemented which define the thresholds for when it will delete files. I think these options are probably too low-level and specific. This is tracked in #13061. Garbage collection of build artifacts is not yet implemented, and tracked in #13136. ### Background This feature is tracked in #12633 and was implemented in a variety of PRs, primarily #12634. The tests for this feature are located in https://github.com/rust-lang/cargo/blob/master/tests/testsuite/global_cache_tracker.rs. Cargo started tracking the last-use data on stable via #13492 in 1.78 which was released 2024-05-02. This PR is proposing to stabilize automatic deletion in 1.82 which will be released in 2024-10-17. ### Risks Users who frequently use versions of Rust older than 1.78 will not have the last-use data tracking updated. If they infrequently use 1.78 or newer, and use the same cache files, then the last-use tracking will only be updated by the newer versions. If that time frame is more than 1 month (or 3 months for downloaded data), then cargo will delete files that the older versions are still using. This means the next time they run the older version, it will have to re-download or re-extract the files. The effects of deleting cache data in environments where cargo's cache is modified by external tools is not fully known. For example, CI caching systems may save and restore cargo's cache. Similarly, things like Docker images that try to save the cache in a layer, or mount the cache in a read-only filesystem may have undesirable interactions. The once-a-day performance hit might be noticeable to some people. I've been using this for several months, and almost never notice it. However, slower systems, or situations where there is a lot of data to delete might take a while (on the order of seconds hopefully).
2 parents ee85ada + 659e274 commit 12555be

File tree

5 files changed

+218
-183
lines changed

5 files changed

+218
-183
lines changed

src/cargo/core/gc.rs

+53-34
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ const DEFAULT_AUTO_FREQUENCY: &str = "1 day";
4949
/// It should be cheap to call this multiple times (subsequent calls are
5050
/// ignored), but try not to abuse that.
5151
pub fn auto_gc(gctx: &GlobalContext) {
52-
if !gctx.cli_unstable().gc {
53-
return;
54-
}
5552
if !gctx.network_allowed() {
5653
// As a conservative choice, auto-gc is disabled when offline. If the
5754
// user is indefinitely offline, we don't want to delete things they
@@ -174,49 +171,74 @@ impl GcOpts {
174171
let config = gctx
175172
.get::<Option<GlobalCleanConfig>>("cache.global-clean")?
176173
.unwrap_or_default();
177-
self.update_for_auto_gc_config(&config)
174+
self.update_for_auto_gc_config(&config, gctx.cli_unstable().gc)
178175
}
179176

180-
fn update_for_auto_gc_config(&mut self, config: &GlobalCleanConfig) -> CargoResult<()> {
177+
fn update_for_auto_gc_config(
178+
&mut self,
179+
config: &GlobalCleanConfig,
180+
unstable_allowed: bool,
181+
) -> CargoResult<()> {
182+
macro_rules! config_default {
183+
($config:expr, $field:ident, $default:expr, $unstable_allowed:expr) => {
184+
if !unstable_allowed {
185+
// These config options require -Zgc
186+
$default
187+
} else {
188+
$config.$field.as_deref().unwrap_or($default)
189+
}
190+
};
191+
}
192+
181193
self.max_src_age = newer_time_span_for_config(
182194
self.max_src_age,
183-
"cache.global-clean.max-src-age",
184-
config
185-
.max_src_age
186-
.as_deref()
187-
.unwrap_or(DEFAULT_MAX_AGE_EXTRACTED),
195+
"gc.auto.max-src-age",
196+
config_default!(
197+
config,
198+
max_src_age,
199+
DEFAULT_MAX_AGE_EXTRACTED,
200+
unstable_allowed
201+
),
188202
)?;
189203
self.max_crate_age = newer_time_span_for_config(
190204
self.max_crate_age,
191-
"cache.global-clean.max-crate-age",
192-
config
193-
.max_crate_age
194-
.as_deref()
195-
.unwrap_or(DEFAULT_MAX_AGE_DOWNLOADED),
205+
"gc.auto.max-crate-age",
206+
config_default!(
207+
config,
208+
max_crate_age,
209+
DEFAULT_MAX_AGE_DOWNLOADED,
210+
unstable_allowed
211+
),
196212
)?;
197213
self.max_index_age = newer_time_span_for_config(
198214
self.max_index_age,
199-
"cache.global-clean.max-index-age",
200-
config
201-
.max_index_age
202-
.as_deref()
203-
.unwrap_or(DEFAULT_MAX_AGE_DOWNLOADED),
215+
"gc.auto.max-index-age",
216+
config_default!(
217+
config,
218+
max_index_age,
219+
DEFAULT_MAX_AGE_DOWNLOADED,
220+
unstable_allowed
221+
),
204222
)?;
205223
self.max_git_co_age = newer_time_span_for_config(
206224
self.max_git_co_age,
207-
"cache.global-clean.max-git-co-age",
208-
config
209-
.max_git_co_age
210-
.as_deref()
211-
.unwrap_or(DEFAULT_MAX_AGE_EXTRACTED),
225+
"gc.auto.max-git-co-age",
226+
config_default!(
227+
config,
228+
max_git_co_age,
229+
DEFAULT_MAX_AGE_EXTRACTED,
230+
unstable_allowed
231+
),
212232
)?;
213233
self.max_git_db_age = newer_time_span_for_config(
214234
self.max_git_db_age,
215-
"cache.global-clean.max-git-db-age",
216-
config
217-
.max_git_db_age
218-
.as_deref()
219-
.unwrap_or(DEFAULT_MAX_AGE_DOWNLOADED),
235+
"gc.auto.max-git-db-age",
236+
config_default!(
237+
config,
238+
max_git_db_age,
239+
DEFAULT_MAX_AGE_DOWNLOADED,
240+
unstable_allowed
241+
),
220242
)?;
221243
Ok(())
222244
}
@@ -255,9 +277,6 @@ impl<'a, 'gctx> Gc<'a, 'gctx> {
255277
/// This returns immediately without doing work if garbage collection has
256278
/// been performed recently (since `cache.auto-clean-frequency`).
257279
fn auto(&mut self, clean_ctx: &mut CleanContext<'gctx>) -> CargoResult<()> {
258-
if !self.gctx.cli_unstable().gc {
259-
return Ok(());
260-
}
261280
let freq = self
262281
.gctx
263282
.get::<Option<String>>("cache.auto-clean-frequency")?;
@@ -274,7 +293,7 @@ impl<'a, 'gctx> Gc<'a, 'gctx> {
274293
.unwrap_or_default();
275294

276295
let mut gc_opts = GcOpts::default();
277-
gc_opts.update_for_auto_gc_config(&config)?;
296+
gc_opts.update_for_auto_gc_config(&config, self.gctx.cli_unstable().gc)?;
278297
self.gc(clean_ctx, &gc_opts)?;
279298
if !clean_ctx.dry_run {
280299
self.global_cache_tracker.set_last_auto_gc()?;

src/doc/src/reference/config.md

+38
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ ENV_VAR_NAME_3 = { value = "relative/path", relative = true }
9595
[future-incompat-report]
9696
frequency = 'always' # when to display a notification about a future incompat report
9797

98+
[cache]
99+
auto-clean-frequency = "1 day" # How often to perform automatic cache cleaning
100+
98101
[cargo-new]
99102
vcs = "none" # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none')
100103

@@ -664,6 +667,41 @@ Controls how often we display a notification to the terminal when a future incom
664667
* `always` (default): Always display a notification when a command (e.g. `cargo build`) produces a future incompat report
665668
* `never`: Never display a notification
666669

670+
### `[cache]`
671+
672+
The `[cache]` table defines settings for cargo's caches.
673+
674+
#### Global caches
675+
676+
When running `cargo` commands, Cargo will automatically track which files you are using within the global cache.
677+
Periodically, Cargo will delete files that have not been used for some period of time.
678+
It will delete files that have to be downloaded from the network if they have not been used in 3 months. Files that can be generated without network access will be deleted if they have not been used in 1 month.
679+
680+
The automatic deletion of files only occurs when running commands that are already doing a significant amount of work, such as all of the build commands (`cargo build`, `cargo test`, `cargo check`, etc.), and `cargo fetch`.
681+
682+
Automatic deletion is disabled if cargo is offline such as with `--offline` or `--frozen` to avoid deleting artifacts that may need to be used if you are offline for a long period of time.
683+
684+
> **Note**: This tracking is currently only implemented for the global cache in Cargo's home directory.
685+
> This includes registry indexes and source files downloaded from registries and git dependencies.
686+
> Support for tracking build artifacts is not yet implemented, and tracked in [cargo#13136](https://github.com/rust-lang/cargo/issues/13136).
687+
>
688+
> Additionally, there is an unstable feature to support *manually* triggering cache cleaning, and to further customize the configuration options.
689+
> See the [Unstable chapter](unstable.md#gc) for more information.
690+
691+
#### `cache.auto-clean-frequency`
692+
* Type: string
693+
* Default: `"1 day"`
694+
* Environment: `CARGO_CACHE_AUTO_CLEAN_FREQUENCY`
695+
696+
This option defines how often Cargo will automatically delete unused files in the global cache.
697+
This does *not* define how old the files must be, those thresholds are described [above](#global-caches).
698+
699+
It supports the following settings:
700+
701+
* `"never"` --- Never deletes old files.
702+
* `"always"` --- Checks to delete old files every time Cargo runs.
703+
* An integer followed by "seconds", "minutes", "hours", "days", "weeks", or "months" --- Checks to delete old files at most the given time frame.
704+
667705
### `[http]`
668706

669707
The `[http]` table defines settings for HTTP behavior. This includes fetching

src/doc/src/reference/environment-variables.md

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ In summary, the supported environment variables are:
9999
* `CARGO_BUILD_RUSTDOCFLAGS` --- Extra `rustdoc` flags, see [`build.rustdocflags`].
100100
* `CARGO_BUILD_INCREMENTAL` --- Incremental compilation, see [`build.incremental`].
101101
* `CARGO_BUILD_DEP_INFO_BASEDIR` --- Dep-info relative directory, see [`build.dep-info-basedir`].
102+
* `CARGO_CACHE_AUTO_CLEAN_FREQUENCY` --- Configures how often automatic cache cleaning runs, see [`cache.auto-clean-frequency`].
102103
* `CARGO_CARGO_NEW_VCS` --- The default source control system with [`cargo new`], see [`cargo-new.vcs`].
103104
* `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY` --- How often we should generate a future incompat report notification, see [`future-incompat-report.frequency`].
104105
* `CARGO_HTTP_DEBUG` --- Enables HTTP debugging, see [`http.debug`].
@@ -163,6 +164,7 @@ In summary, the supported environment variables are:
163164
[`build.incremental`]: config.md#buildincremental
164165
[`build.dep-info-basedir`]: config.md#builddep-info-basedir
165166
[`doc.browser`]: config.md#docbrowser
167+
[`cache.auto-clean-frequency`]: config.md#cacheauto-clean-frequency
166168
[`cargo-new.name`]: config.md#cargo-newname
167169
[`cargo-new.email`]: config.md#cargo-newemail
168170
[`cargo-new.vcs`]: config.md#cargo-newvcs

src/doc/src/reference/unstable.md

+14-27
Original file line numberDiff line numberDiff line change
@@ -1587,37 +1587,16 @@ This will not affect any hard-coded paths in the source code, such as in strings
15871587

15881588
* Tracking Issue: [#12633](https://github.com/rust-lang/cargo/issues/12633)
15891589

1590-
The `-Zgc` flag enables garbage-collection within cargo's global cache within the cargo home directory.
1591-
This includes downloaded dependencies such as compressed `.crate` files, extracted `src` directories, registry index caches, and git dependencies.
1592-
When `-Zgc` is present, cargo will track the last time any index and dependency was used,
1593-
and then uses those timestamps to manually or automatically delete cache entries that have not been used for a while.
1594-
1595-
```sh
1596-
cargo build -Zgc
1597-
```
1598-
1599-
### Automatic garbage collection
1600-
1601-
Automatic deletion happens on commands that are already doing a significant amount of work,
1602-
such as all of the build commands (`cargo build`, `cargo test`, `cargo check`, etc.), and `cargo fetch`.
1603-
The deletion happens just after resolution and packages have been downloaded.
1604-
Automatic deletion is only done once per day (see `cache.auto-clean-frequency` to configure).
1605-
Automatic deletion is disabled if cargo is offline such as with `--offline` or `--frozen` to avoid deleting artifacts that may need to be used if you are offline for a long period of time.
1590+
The `-Zgc` flag is used to enable certain features related to garbage-collection of cargo's global cache within the cargo home directory.
16061591

16071592
#### Automatic gc configuration
16081593

1609-
The automatic gc behavior can be specified via a cargo configuration setting.
1594+
The `-Zgc` flag will enable Cargo to read extra configuration options related to garbage collection.
16101595
The settings available are:
16111596

16121597
```toml
16131598
# Example config.toml file.
16141599

1615-
# This table defines settings for cargo's caches.
1616-
[cache]
1617-
# The maximum frequency that automatic cleaning of the cache happens.
1618-
# Can be "never" to disable, or "always" to run on every command.
1619-
auto-clean-frequency = "1 day"
1620-
16211600
# Sub-table for defining specific settings for cleaning the global cache.
16221601
[cache.global-clean]
16231602
# Anything older than this duration will be deleted in the source cache.
@@ -1632,9 +1611,13 @@ max-git-co-age = "1 month"
16321611
max-git-db-age = "3 months"
16331612
```
16341613

1614+
Note that the [`cache.auto-clean-frequency`] option was stabilized in Rust 1.88.
1615+
1616+
[`cache.auto-clean-frequency`]: config.md#cacheauto-clean-frequency
1617+
16351618
### Manual garbage collection with `cargo clean`
16361619

1637-
Manual deletion can be done with the `cargo clean gc` command.
1620+
Manual deletion can be done with the `cargo clean gc -Zgc` command.
16381621
Deletion of cache contents can be performed by passing one of the cache options:
16391622

16401623
- `--max-src-age=DURATION` --- Deletes source cache files that have not been used since the given age.
@@ -1653,9 +1636,9 @@ A DURATION is specified in the form "N seconds/minutes/days/weeks/months" where
16531636
A SIZE is specified in the form "N *suffix*" where *suffix* is B, kB, MB, GB, kiB, MiB, or GiB, and N is an integer or floating point number. If no suffix is specified, the number is the number of bytes.
16541637

16551638
```sh
1656-
cargo clean gc
1657-
cargo clean gc --max-download-age=1week
1658-
cargo clean gc --max-git-size=0 --max-download-size=100MB
1639+
cargo clean gc -Zgc
1640+
cargo clean gc -Zgc --max-download-age=1week
1641+
cargo clean gc -Zgc --max-git-size=0 --max-download-size=100MB
16591642
```
16601643

16611644
## open-namespaces
@@ -2166,3 +2149,7 @@ The 2024 edition has been stabilized in the 1.85 release.
21662149
See the [`edition` field](manifest.md#the-edition-field) for more information on setting the edition.
21672150
See [`cargo fix --edition`](../commands/cargo-fix.md) and [The Edition Guide](../../edition-guide/index.html) for more information on migrating existing projects.
21682151

2152+
## Automatic garbage collection
2153+
2154+
Support for automatically deleting old files was stabilized in Rust 1.88.
2155+
More information can be found in the [config chapter](config.md#cache).

0 commit comments

Comments
 (0)