Skip to content

Commit 4bc7083

Browse files
author
Junio C Hamano
committed
Merge branch 'np/pack'
* np/pack: fix repack with --max-pack-size builtin-pack-object: cache small deltas git-pack-objects: cache small deltas between big objects builtin-pack-objects: don't fail, if delta is not possible
2 parents 17c2929 + 5476a8a commit 4bc7083

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

Documentation/config.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,15 @@ pack.compression::
568568
slowest. If not set, defaults to core.compression. If that is
569569
not set, defaults to -1.
570570

571+
pack.deltaCacheSize::
572+
The maxium memory in bytes used for caching deltas in
573+
gitlink:git-pack-objects[1].
574+
A value of 0 means no limit. Defaults to 0.
575+
576+
pack.deltaCacheLimit::
577+
The maxium size of a delta, that is cached in
578+
gitlink:git-pack-objects[1]. Defaults to 1000.
579+
571580
pull.octopus::
572581
The default merge strategy to use when pulling multiple branches
573582
at once.

builtin-pack-objects.c

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct object_entry {
3636
struct object_entry *delta_sibling; /* other deltified objects who
3737
* uses the same base as me
3838
*/
39+
void *delta_data; /* cached delta (uncompressed) */
3940
unsigned long delta_size; /* delta data size (uncompressed) */
4041
enum object_type type;
4142
enum object_type in_pack_type; /* could be delta */
@@ -76,6 +77,10 @@ static struct progress progress_state;
7677
static int pack_compression_level = Z_DEFAULT_COMPRESSION;
7778
static int pack_compression_seen;
7879

80+
static unsigned long delta_cache_size = 0;
81+
static unsigned long max_delta_cache_size = 0;
82+
static unsigned long cache_max_small_delta_size = 1000;
83+
7984
/*
8085
* The object names in objects array are hashed with this hashtable,
8186
* to help looking up the entry by object name.
@@ -405,24 +410,24 @@ static unsigned long write_object(struct sha1file *f,
405410
z_stream stream;
406411
unsigned long maxsize;
407412
void *out;
408-
buf = read_sha1_file(entry->sha1, &type, &size);
409-
if (!buf)
410-
die("unable to read %s", sha1_to_hex(entry->sha1));
411-
if (size != entry->size)
412-
die("object %s size inconsistency (%lu vs %lu)",
413-
sha1_to_hex(entry->sha1), size, entry->size);
414-
if (usable_delta) {
415-
buf = delta_against(buf, size, entry);
413+
if (!usable_delta) {
414+
buf = read_sha1_file(entry->sha1, &obj_type, &size);
415+
if (!buf)
416+
die("unable to read %s", sha1_to_hex(entry->sha1));
417+
} else if (entry->delta_data) {
416418
size = entry->delta_size;
419+
buf = entry->delta_data;
420+
entry->delta_data = NULL;
417421
obj_type = (allow_ofs_delta && entry->delta->offset) ?
418422
OBJ_OFS_DELTA : OBJ_REF_DELTA;
419423
} else {
420-
/*
421-
* recover real object type in case
422-
* check_object() wanted to re-use a delta,
423-
* but we couldn't since base was in previous split pack
424-
*/
425-
obj_type = type;
424+
buf = read_sha1_file(entry->sha1, &type, &size);
425+
if (!buf)
426+
die("unable to read %s", sha1_to_hex(entry->sha1));
427+
buf = delta_against(buf, size, entry);
428+
size = entry->delta_size;
429+
obj_type = (allow_ofs_delta && entry->delta->offset) ?
430+
OBJ_OFS_DELTA : OBJ_REF_DELTA;
426431
}
427432
/* compress the data to store and put compressed length in datalen */
428433
memset(&stream, 0, sizeof(stream));
@@ -1385,6 +1390,23 @@ struct unpacked {
13851390
struct delta_index *index;
13861391
};
13871392

1393+
static int delta_cacheable(struct unpacked *trg, struct unpacked *src,
1394+
unsigned long src_size, unsigned long trg_size,
1395+
unsigned long delta_size)
1396+
{
1397+
if (max_delta_cache_size && delta_cache_size + delta_size > max_delta_cache_size)
1398+
return 0;
1399+
1400+
if (delta_size < cache_max_small_delta_size)
1401+
return 1;
1402+
1403+
/* cache delta, if objects are large enough compared to delta size */
1404+
if ((src_size >> 20) + (trg_size >> 21) > (delta_size >> 10))
1405+
return 1;
1406+
1407+
return 0;
1408+
}
1409+
13881410
/*
13891411
* We search for deltas _backwards_ in a list sorted by type and
13901412
* by size, so that we see progressively smaller and smaller files.
@@ -1454,18 +1476,32 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
14541476
}
14551477
if (!src->index) {
14561478
src->index = create_delta_index(src->data, src_size);
1457-
if (!src->index)
1458-
die("out of memory");
1479+
if (!src->index) {
1480+
static int warned = 0;
1481+
if (!warned++)
1482+
warning("suboptimal pack - out of memory");
1483+
return 0;
1484+
}
14591485
}
14601486

14611487
delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
14621488
if (!delta_buf)
14631489
return 0;
14641490

1491+
if (trg_entry->delta_data) {
1492+
delta_cache_size -= trg_entry->delta_size;
1493+
free(trg_entry->delta_data);
1494+
}
1495+
trg_entry->delta_data = 0;
14651496
trg_entry->delta = src_entry;
14661497
trg_entry->delta_size = delta_size;
14671498
trg_entry->depth = src_entry->depth + 1;
1468-
free(delta_buf);
1499+
1500+
if (delta_cacheable(src, trg, src_size, trg_size, delta_size)) {
1501+
trg_entry->delta_data = xrealloc(delta_buf, delta_size);
1502+
delta_cache_size += trg_entry->delta_size;
1503+
} else
1504+
free(delta_buf);
14691505
return 1;
14701506
}
14711507

@@ -1611,6 +1647,14 @@ static int git_pack_config(const char *k, const char *v)
16111647
pack_compression_seen = 1;
16121648
return 0;
16131649
}
1650+
if (!strcmp(k, "pack.deltacachesize")) {
1651+
max_delta_cache_size = git_config_int(k, v);
1652+
return 0;
1653+
}
1654+
if (!strcmp(k, "pack.deltacachelimit")) {
1655+
cache_max_small_delta_size = git_config_int(k, v);
1656+
return 0;
1657+
}
16141658
return git_default_config(k, v);
16151659
}
16161660

0 commit comments

Comments
 (0)