gc: handle a corner case in gc.bigPackThreshold

This config allows us to keep <N> packs back if their size is larger than a limit. But if this N >= gc.autoPackLimit, we may have a problem. We are supposed to reduce the number of packs after a threshold because it affects performance. We could tell the user that they have incompatible gc.bigPackThreshold and gc.autoPackLimit, but it's kinda hard when 'git gc --auto' runs in background. Instead let's fall back to the next best stategy: try to reduce the number of packs anyway, but keep the base pack out. This reduces the number of packs to two and hopefully won't take up too much resources to repack (the assumption still is the base pack takes most resources to handle). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Apr 15, 2018 at 17:36 UTC 8fc67762471c60ee644e6e100a3a85cf5a8631a0
2 files changed +12 -1
Documentation/config.txt
+5
@@ -1564,6 +1564,11 @@ gc.bigPackThreshold::
1564 except that all packs that meet the threshold are kept, not
1565 just the base pack. Defaults to zero. Common unit suffixes of
1566 'k', 'm', or 'g' are supported.
1567 ++
1568 +Note that if the number of kept packs is more than gc.autoPackLimit,
1569 +this configuration variable is ignored, all packs except the base pack
1570 +will be repacked. After this the number of packs should go below
1571 +gc.autoPackLimit and gc.bigPackThreshold should be respected again.
1572
1573 gc.logExpiry::
1574 If the file gc.log exists, then `git gc --auto` won't run
builtin/gc.c
+7 -1
@@ -253,8 +253,14 @@ static int need_to_gc(void)
253 if (too_many_packs()) {
254 struct string_list keep_pack = STRING_LIST_INIT_NODUP;
255
256 - if (big_pack_threshold)
256 + if (big_pack_threshold) {
257 find_base_packs(&keep_pack, big_pack_threshold);
258 + if (keep_pack.nr >= gc_auto_pack_limit) {
259 + big_pack_threshold = 0;
260 + string_list_clear(&keep_pack, 0);
261 + find_base_packs(&keep_pack, 0);
262 + }
263 + }
264
265 add_repack_all_option(&keep_pack);
266 string_list_clear(&keep_pack, 0);