diff mbox series

[v2,09/10] builtin/gc.c: make `gc.cruftPacks` enabled by default

Message ID b6784ddfe2906f7c04b3050bd9ba63a884ddb047.1681850424.git.me@ttaylorr.com (mailing list archive)
State Accepted
Commit e3e24de1bf1fd443978015fe06bb523dc85a3086
Headers show
Series gc: enable cruft packs by default | expand

Commit Message

Taylor Blau April 18, 2023, 8:40 p.m. UTC
Back in 5b92477f89 (builtin/gc.c: conditionally avoid pruning objects
via loose, 2022-05-20), `git gc` learned the `--cruft` option and
`gc.cruftPacks` configuration to opt-in to writing cruft packs when
collecting or pruning unreachable objects.

Cruft packs were introduced with the merge in a50036da1a (Merge branch
'tb/cruft-packs', 2022-06-03). They address the problem of "loose object
explosions", where Git will write out many individual loose objects when
there is a large number of unreachable objects that have not yet aged
past `--prune=<date>`.

Instead of keeping track of those unreachable yet recent objects via
their loose object file's mtime, cruft packs collect all unreachable
objects into a single pack with a corresponding `*.mtimes` file that
acts as a table to store the mtimes of all unreachable objects. This
prevents the need to store unreachable objects as loose as they age out
of the repository, and avoids the problem of loose object explosions.

Beyond avoiding loose object explosions, cruft packs also act as a more
efficient mechanism to store unreachable objects as they age out of a
repository. This is because pairs of similar unreachable objects serve
as delta bases for one another.

In 5b92477f89, the feature was introduced as experimental. Since then,
GitHub has been running these patches in every repository generating
hundreds of millions of cruft packs along the way. The feature is
battle-tested, and avoids many pathological cases such as above. Users
who either run `git gc` manually, or via `git maintenance` can benefit
from having cruft packs.

As such, enable cruft pack generation to take place by default (by
making `gc.cruftPacks` have the default of "true" rather than "false).

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 Documentation/config/feature.txt |  3 ---
 Documentation/config/gc.txt      |  2 +-
 Documentation/git-gc.txt         |  5 +++--
 Documentation/gitformat-pack.txt |  4 ++--
 builtin/gc.c                     |  6 +-----
 t/t6500-gc.sh                    | 12 ++++--------
 6 files changed, 11 insertions(+), 21 deletions(-)

Comments

Junio C Hamano April 19, 2023, 10:22 p.m. UTC | #1
Taylor Blau <me@ttaylorr.com> writes:

> diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
> index e52bc6b858..17b4d39f89 100644
> --- a/Documentation/config/feature.txt
> +++ b/Documentation/config/feature.txt
> @@ -14,9 +14,6 @@ feature.experimental::
>  +
>  * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
>  skipping more commits at a time, reducing the number of round trips.
> -+
> -* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
> -garbage collection, preventing loose object explosions.

Being listed here is a definite sign that a feature behind a
configuration variable is considered experimental.  Do we have (and
if not, do we want to establish) a procedure to mark and announce a
feature that used to be experimental no longer is?  If it is enough
to mention it in the release notes, then I can take care of it, of
course.
Taylor Blau April 20, 2023, 5:24 p.m. UTC | #2
On Wed, Apr 19, 2023 at 03:22:13PM -0700, Junio C Hamano wrote:
> Taylor Blau <me@ttaylorr.com> writes:
>
> > diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
> > index e52bc6b858..17b4d39f89 100644
> > --- a/Documentation/config/feature.txt
> > +++ b/Documentation/config/feature.txt
> > @@ -14,9 +14,6 @@ feature.experimental::
> >  +
> >  * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
> >  skipping more commits at a time, reducing the number of round trips.
> > -+
> > -* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
> > -garbage collection, preventing loose object explosions.
>
> Being listed here is a definite sign that a feature behind a
> configuration variable is considered experimental.  Do we have (and
> if not, do we want to establish) a procedure to mark and announce a
> feature that used to be experimental no longer is?  If it is enough
> to mention it in the release notes, then I can take care of it, of
> course.

I am not aware of such a procedure. But personally I think it would be
fine to mention it in the release notes for the next release.

Thanks,
Taylor
Junio C Hamano April 20, 2023, 5:31 p.m. UTC | #3
Taylor Blau <me@ttaylorr.com> writes:

>> Being listed here is a definite sign that a feature behind a
>> configuration variable is considered experimental.  Do we have (and
>> if not, do we want to establish) a procedure to mark and announce a
>> feature that used to be experimental no longer is?  If it is enough
>> to mention it in the release notes, then I can take care of it, of
>> course.
>
> I am not aware of such a procedure. But personally I think it would be
> fine to mention it in the release notes for the next release.

OK.  I updated the entry for the topic in the draft "What's cooking"
report to read:

    * tb/enable-cruft-packs-by-default (2023-04-18) 10 commits
     - ...

     When "gc" needs to retain unreachable objects, packing them into
     cruft packs (instead of exploding them into loose object files) has
     been offered as a more efficient option for some time.  Now the use
     of cruft packs has been made the default and no longer considered
     an experimental feature.

     Will merge to 'next'.
     source: <cover.1681850424.git.me@ttaylorr.com>

and the per-topic description text is usually what is copied
verbatim to the release notes, so even if I forget, the procedure
will remember it for us ;-)

Thanks.
Taylor Blau April 20, 2023, 7:19 p.m. UTC | #4
On Thu, Apr 20, 2023 at 10:31:00AM -0700, Junio C Hamano wrote:
> Taylor Blau <me@ttaylorr.com> writes:
>
> >> Being listed here is a definite sign that a feature behind a
> >> configuration variable is considered experimental.  Do we have (and
> >> if not, do we want to establish) a procedure to mark and announce a
> >> feature that used to be experimental no longer is?  If it is enough
> >> to mention it in the release notes, then I can take care of it, of
> >> course.
> >
> > I am not aware of such a procedure. But personally I think it would be
> > fine to mention it in the release notes for the next release.
>
> OK.  I updated the entry for the topic in the draft "What's cooking"
> report to read:
>
>     * tb/enable-cruft-packs-by-default (2023-04-18) 10 commits
>      - ...
>
>      When "gc" needs to retain unreachable objects, packing them into
>      cruft packs (instead of exploding them into loose object files) has
>      been offered as a more efficient option for some time.  Now the use
>      of cruft packs has been made the default and no longer considered
>      an experimental feature.
>
>      Will merge to 'next'.
>      source: <cover.1681850424.git.me@ttaylorr.com>

Thanks, I think that summarizes/announces the change well. I always
appreciate your effort into concisely summarizing the topics being
queued.

> and the per-topic description text is usually what is copied
> verbatim to the release notes, so even if I forget, the procedure
> will remember it for us ;-)

;-).

Thanks,
Taylor
diff mbox series

Patch

diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
index e52bc6b858..17b4d39f89 100644
--- a/Documentation/config/feature.txt
+++ b/Documentation/config/feature.txt
@@ -14,9 +14,6 @@  feature.experimental::
 +
 * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
 skipping more commits at a time, reducing the number of round trips.
-+
-* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
-garbage collection, preventing loose object explosions.
 
 feature.manyFiles::
 	Enable config options that optimize for repos with many files in the
diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt
index 8d5353e9e0..7f95c866e1 100644
--- a/Documentation/config/gc.txt
+++ b/Documentation/config/gc.txt
@@ -84,7 +84,7 @@  gc.packRefs::
 gc.cruftPacks::
 	Store unreachable objects in a cruft pack (see
 	linkgit:git-repack[1]) instead of as loose objects. The default
-	is `false`.
+	is `true`.
 
 gc.pruneExpire::
 	When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index fef382a70f..90806fd26a 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -54,9 +54,10 @@  other housekeeping tasks (e.g. rerere, working trees, reflog...) will
 be performed as well.
 
 
---cruft::
+--[no-]cruft::
 	When expiring unreachable objects, pack them separately into a
-	cruft pack instead of storing them as loose objects.
+	cruft pack instead of storing them as loose objects. `--cruft`
+	is on by default.
 
 --prune=<date>::
 	Prune loose objects older than date (default is 2 weeks ago,
diff --git a/Documentation/gitformat-pack.txt b/Documentation/gitformat-pack.txt
index e06af02f21..0c1be2dbe8 100644
--- a/Documentation/gitformat-pack.txt
+++ b/Documentation/gitformat-pack.txt
@@ -611,8 +611,8 @@  result of repeatedly resetting the objects' mtimes to the present time.
 
 If you are GC-ing repositories in a mixed version environment, consider omitting
 the `--cruft` option when using linkgit:git-repack[1] and linkgit:git-gc[1], and
-leaving the `gc.cruftPacks` configuration unset until all writers understand
-cruft packs.
+setting the `gc.cruftPacks` configuration to "false" until all writers
+understand cruft packs.
 
 === Alternatives
 
diff --git a/builtin/gc.c b/builtin/gc.c
index 53ef137e1d..ece01e966f 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -48,7 +48,7 @@  static const char * const builtin_gc_usage[] = {
 
 static int pack_refs = 1;
 static int prune_reflogs = 1;
-static int cruft_packs = -1;
+static int cruft_packs = 1;
 static int aggressive_depth = 50;
 static int aggressive_window = 250;
 static int gc_auto_threshold = 6700;
@@ -608,10 +608,6 @@  int cmd_gc(int argc, const char **argv, const char *prefix)
 	if (prune_expire && parse_expiry_date(prune_expire, &dummy))
 		die(_("failed to parse prune expiry value %s"), prune_expire);
 
-	prepare_repo_settings(the_repository);
-	if (cruft_packs < 0)
-		cruft_packs = the_repository->settings.gc_cruft_packs;
-
 	if (aggressive) {
 		strvec_push(&repack, "-f");
 		if (aggressive_depth > 0)
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index 3ba2ae5140..69509d0c11 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -216,11 +216,9 @@  assert_no_cruft_packs () {
 }
 
 for argv in \
-	"gc --cruft" \
+	"gc" \
 	"-c gc.cruftPacks=true gc" \
-	"-c gc.cruftPacks=false gc --cruft" \
-	"-c feature.experimental=true gc" \
-	"-c gc.cruftPacks=true -c feature.experimental=false gc"
+	"-c gc.cruftPacks=false gc --cruft"
 do
 	test_expect_success "git $argv generates a cruft pack" '
 		test_when_finished "rm -fr repo" &&
@@ -244,11 +242,9 @@  do
 done
 
 for argv in \
-	"gc" \
+	"gc --no-cruft" \
 	"-c gc.cruftPacks=false gc" \
-	"-c gc.cruftPacks=true gc --no-cruft" \
-	"-c feature.expiremental=true -c gc.cruftPacks=false gc" \
-	"-c feature.experimental=false gc"
+	"-c gc.cruftPacks=true gc --no-cruft"
 do
 	test_expect_success "git $argv does not generate a cruft pack" '
 		test_when_finished "rm -fr repo" &&